1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15- package main
15+ package command
1616
1717import (
18+ "bytes"
1819 "errors"
1920 "fmt"
21+ "io"
2022 "os"
2123 "strings"
2224
@@ -25,9 +27,9 @@ import (
2527)
2628
2729type ConvertCmd struct {
28- Input string `arg:"" name:"input" help:"Input file." type:"existingfile "`
30+ Input string `arg:"" optional:"" name:"input" help:"Input file. If not provided, input is read from stdin. " type:"path "`
2931 From string `help:"Input file format. Possible values: ${enum}." enum:"auto, geojson, geoparquet, parquet" default:"auto"`
30- Output string `arg:"" name:"output" help:"Output file." type:"path"`
32+ Output string `arg:"" optional:"" name:"output" help:"Output file. If not provided, output is written to stdout ." type:"path"`
3133 To string `help:"Output file format. Possible values: ${enum}." enum:"auto, geojson, geoparquet" default:"auto"`
3234 Min int `help:"Minimum number of features to consider when building a schema." default:"10"`
3335 Max int `help:"Maximum number of features to consider when building a schema." default:"100"`
@@ -53,6 +55,9 @@ var validTypes = map[FormatType]bool{
5355}
5456
5557func parseFormatType (format string ) FormatType {
58+ if format == "" {
59+ return AutoType
60+ }
5661 ft := FormatType (strings .ToLower (format ))
5762 if ! validTypes [ft ] {
5863 return UnknownType
@@ -73,34 +78,72 @@ func getFormatType(filename string) FormatType {
7378 return UnknownType
7479}
7580
81+ func hasStdin () bool {
82+ stats , err := os .Stdin .Stat ()
83+ if err != nil {
84+ return false
85+ }
86+ return stats .Size () > 0
87+ }
88+
7689func (c * ConvertCmd ) Run () error {
90+ inputSource := c .Input
91+ outputSource := c .Output
92+
93+ if outputSource == "" && hasStdin () {
94+ outputSource = inputSource
95+ inputSource = ""
96+ }
97+
7798 outputFormat := parseFormatType (c .To )
7899 if outputFormat == AutoType {
79- outputFormat = getFormatType (c .Output )
100+ if outputSource == "" {
101+ return fmt .Errorf ("when writing to stdout, the --to option must be provided to determine the output format" )
102+ }
103+ outputFormat = getFormatType (outputSource )
80104 }
81105 if outputFormat == UnknownType {
82- return fmt .Errorf ("could not determine output format for %s" , c . Output )
106+ return fmt .Errorf ("could not determine output format for %s" , outputSource )
83107 }
84108
85109 inputFormat := parseFormatType (c .From )
86110 if inputFormat == AutoType {
87- inputFormat = getFormatType (c .Input )
111+ if inputSource == "" {
112+ return fmt .Errorf ("when reading from stdin, the --from option must be provided to determine the input format" )
113+ }
114+ inputFormat = getFormatType (inputSource )
88115 }
89116 if inputFormat == UnknownType {
90- return fmt .Errorf ("could not determine input format for %s" , c . Input )
117+ return fmt .Errorf ("could not determine input format for %s" , inputSource )
91118 }
92119
93- input , readErr := os .Open (c .Input )
94- if readErr != nil {
95- return fmt .Errorf ("failed to read from %q: %w" , c .Input , readErr )
120+ var input ReaderAtSeeker
121+ if inputSource == "" {
122+ data , err := io .ReadAll (os .Stdin )
123+ if err != nil {
124+ return fmt .Errorf ("trouble reading from stdin: %w" , err )
125+ }
126+ input = bytes .NewReader (data )
127+ } else {
128+ i , readErr := os .Open (inputSource )
129+ if readErr != nil {
130+ return fmt .Errorf ("failed to read from %q: %w" , inputSource , readErr )
131+ }
132+ defer i .Close ()
133+ input = i
96134 }
97- defer input .Close ()
98135
99- output , createErr := os .Create (c .Output )
100- if createErr != nil {
101- return fmt .Errorf ("failed to open %q for writing: %w" , c .Output , createErr )
136+ var output * os.File
137+ if outputSource == "" {
138+ output = os .Stdout
139+ } else {
140+ o , createErr := os .Create (outputSource )
141+ if createErr != nil {
142+ return fmt .Errorf ("failed to open %q for writing: %w" , outputSource , createErr )
143+ }
144+ defer o .Close ()
145+ output = o
102146 }
103- defer output .Close ()
104147
105148 if inputFormat == GeoJSONType {
106149 if outputFormat != ParquetType && outputFormat != GeoParquetType {
0 commit comments