config-rs icon indicating copy to clipboard operation
config-rs copied to clipboard

YAML: incorrect parsing of curly brackets

Open odyslam opened this issue 2 years ago • 2 comments

When parsing curly brackets, even as a string ("${env_var}"), it decodes the curly brackets to it's ASCII code. This is probably a bug of the underlying yaml library (yaml-rust).

I solved it by not using curly brackets.

odyslam avatar Jun 07 '23 16:06 odyslam

Hi! Thanks for your report. I suspect that this is indeed an issue of the underlying yaml library, since this library does not interfere with parsing AFAIK.

I'll leave this open for discoverability until the yaml lib is fixed. If someone wants to contribute a test for this, I'd love to have that!

matthiasbeyer avatar Jun 12 '23 07:06 matthiasbeyer

Unable to reproduce (not much of a reproduction example given) with:

  • config v0.13.3
  • Windows via WSL2
  • cargo 1.73.0 (9c4383fb5 2023-08-26)

More context is required for this to be valid/reproducible.


Yaml file:

key: "${env_var}"

Rust reproduction main.rs:

use config::{Config, File, FileFormat};
use serde::Deserialize;

fn main() {
  let sources = ConfigSource::vec_example();

  for s in sources {
    let c = s.get_config();
    let test: Test = c.try_deserialize().unwrap();
    println!("{:#?}", test);
  }
}

#[allow(dead_code)]
#[derive(Debug, Deserialize)]
struct Test {
  key: String,
}

fn make<T>(source: T) -> Config
where
  T: config::Source + Send + Sync + 'static,
{
    Config::builder()
        .add_source(source)
        .build()
        .unwrap()
}

// Overkill:
enum ConfigSource {
  String(File<config::FileSourceString, FileFormat>),
  File(File<config::FileSourceFile, FileFormat>),
}

impl ConfigSource {
  fn vec_example() -> Vec<ConfigSource> {
    vec![
      ConfigSource::String(
        File::from_str(r#"key: "${env_var}""#, FileFormat::Yaml)
      ),
      ConfigSource::File(
        File::new("test.yml", FileFormat::Yaml)
      )
    ]
  }

  fn get_config(self) -> Config {
    match self {
      Self::String(s) => make(s),
      Self::File(f) => make(f),
    }
  }
}

Output:

Test {
    key: "${env_var}",
}
Test {
    key: "${env_var}",
}

Raw Config (not deserialized into Test struct):

Config {
    defaults: {},
    overrides: {},
    sources: [],
    cache: Value {
        origin: None,
        kind: Table(
            {
                "key": Value {
                    origin: None,
                    kind: String(
                        "${env_var}",
                    ),
                },
            },
        ),
    },
}

polarathene avatar Oct 20 '23 03:10 polarathene