1616package appext
1717
1818import (
19+ "bytes"
1920 "context"
2021 "errors"
2122 "fmt"
@@ -26,8 +27,8 @@ import (
2627 "time"
2728
2829 "github.com/bufbuild/buf/private/pkg/app"
29- "github.com/bufbuild/buf/private/pkg/encoding"
3030 "github.com/spf13/pflag"
31+ "gopkg.in/yaml.v3"
3132)
3233
3334const (
@@ -167,7 +168,7 @@ func ReadConfig(container NameContainer, value any) error {
167168 if err != nil {
168169 return fmt .Errorf ("could not read %s configuration file at %s: %w" , container .AppName (), configFilePath , err )
169170 }
170- if err := encoding . UnmarshalYAMLStrict (data , value ); err != nil {
171+ if err := unmarshalYAMLStrict (data , value ); err != nil {
171172 return fmt .Errorf ("invalid %s configuration file: %w" , container .AppName (), err )
172173 }
173174 }
@@ -186,7 +187,7 @@ func ReadConfigNonStrict(container NameContainer, value any) error {
186187 if err != nil {
187188 return fmt .Errorf ("could not read %s configuration file at %s: %w" , container .AppName (), configFilePath , err )
188189 }
189- if err := encoding . UnmarshalYAMLNonStrict (data , value ); err != nil {
190+ if err := unmarshalYAMLNonStrict (data , value ); err != nil {
190191 return fmt .Errorf ("invalid %s configuration file: %w" , container .AppName (), err )
191192 }
192193 }
@@ -210,7 +211,7 @@ func ReadSecret(container NameContainer, name string) (string, error) {
210211// The directory is created if it does not exist.
211212// The value should be a pointer to marshal.
212213func WriteConfig (container NameContainer , value any ) error {
213- data , err := encoding . MarshalYAML (value )
214+ data , err := marshalYAML (value )
214215 if err != nil {
215216 return err
216217 }
@@ -239,3 +240,48 @@ func Listen(ctx context.Context, container NameContainer, defaultPort uint16) (n
239240 var listenConfig net.ListenConfig
240241 return listenConfig .Listen (ctx , "tcp" , fmt .Sprintf ("0.0.0.0:%d" , port ))
241242}
243+
244+ // *** PRIVATE ***
245+
246+ // marshalYAML marshals the given value into YAML.
247+ func marshalYAML (v any ) (_ []byte , retErr error ) {
248+ buffer := bytes .NewBuffer (nil )
249+ yamlEncoder := yaml .NewEncoder (buffer )
250+ yamlEncoder .SetIndent (2 )
251+ defer func () {
252+ retErr = errors .Join (retErr , yamlEncoder .Close ())
253+ }()
254+ if err := yamlEncoder .Encode (v ); err != nil {
255+ return nil , err
256+ }
257+ return buffer .Bytes (), nil
258+ }
259+
260+ // unmarshalYAMLStrict unmarshals the data as YAML, returning a user error on failure.
261+ //
262+ // If the data length is 0, this is a no-op.
263+ func unmarshalYAMLStrict (data []byte , v any ) error {
264+ if len (data ) == 0 {
265+ return nil
266+ }
267+ yamlDecoder := yaml .NewDecoder (bytes .NewReader (data ))
268+ yamlDecoder .KnownFields (true )
269+ if err := yamlDecoder .Decode (v ); err != nil {
270+ return fmt .Errorf ("could not unmarshal as YAML: %v" , err )
271+ }
272+ return nil
273+ }
274+
275+ // unmarshalYAMLNonStrict unmarshals the data as YAML, returning a user error on failure.
276+ //
277+ // If the data length is 0, this is a no-op.
278+ func unmarshalYAMLNonStrict (data []byte , v any ) error {
279+ if len (data ) == 0 {
280+ return nil
281+ }
282+ yamlDecoder := yaml .NewDecoder (bytes .NewReader (data ))
283+ if err := yamlDecoder .Decode (v ); err != nil {
284+ return fmt .Errorf ("could not unmarshal as YAML: %v" , err )
285+ }
286+ return nil
287+ }
0 commit comments