Skip to content

Commit

Permalink
feat: json5 source support
Browse files Browse the repository at this point in the history
  • Loading branch information
tenuous-guidance committed Sep 2, 2024
1 parent ad2a63c commit dfa6659
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
2 changes: 2 additions & 0 deletions confik/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ default = ["env", "toml"]
# Source types
env = ["dep:envious"]
json = ["dep:serde_json"]
json5 = ["dep:json5"]
toml = ["dep:toml"]

# Destination types
Expand All @@ -48,6 +49,7 @@ serde = { version = "1", default-features = false, features = ["std", "derive"]
thiserror = "1"

envious = { version = "0.2", optional = true }
json5 = { version = "0.4", optional = true }
serde_json = { version = "1", optional = true }
toml = { version = "0.8", optional = true, default-features = false, features = ["parse"] }

Expand Down
2 changes: 2 additions & 0 deletions confik/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ mod third_party;

#[cfg(feature = "env")]
pub use self::sources::env_source::EnvSource;
#[cfg(feature = "json5")]
pub use self::sources::json5_source::Json5Source;
#[cfg(feature = "json")]
pub use self::sources::json_source::JsonSource;
#[cfg(feature = "toml")]
Expand Down
94 changes: 94 additions & 0 deletions confik/src/sources/json5_source.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::{borrow::Cow, error::Error, fmt};

use crate::{ConfigurationBuilder, Source};

/// A [`Source`] containing raw JSON data.
#[derive(Clone)]
pub struct Json5Source<'a> {
contents: Cow<'a, str>,
allow_secrets: bool,
}

impl<'a> Json5Source<'a> {
/// Creates a [`Source`] containing raw JSON data.
pub fn new(contents: impl Into<Cow<'a, str>>) -> Self {
Self {
contents: contents.into(),
allow_secrets: false,
}
}

/// Allows this source to contain secrets.
pub fn allow_secrets(mut self) -> Self {
self.allow_secrets = true;
self
}
}

impl<'a> Source for Json5Source<'a> {
fn allows_secrets(&self) -> bool {
self.allow_secrets
}

fn provide<T: ConfigurationBuilder>(&self) -> Result<T, Box<dyn Error + Sync + Send>> {
Ok(json5::from_str(&self.contents)?)
}
}

impl<'a> fmt::Debug for Json5Source<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Json5Source")
.field("allow_secrets", &self.allow_secrets)
.finish_non_exhaustive()
}
}

#[cfg(test)]
mod tests {
use crate::Configuration;

use super::*;

#[test]
fn defaults() {
let source = Json5Source::new("{}");
assert!(!source.allows_secrets());
}

#[test]
fn clone() {
let source = Json5Source::new("{}").allow_secrets();
assert!(source.allows_secrets());
assert!(source.clone().allow_secrets);
}

#[test]
fn json5() {
#[derive(Configuration, Debug, PartialEq)]
struct Config {
message: String,
n: i32,
}

let config = "
{
// A traditional message.
message: 'hello world',
// A number for some reason.
n: 42,
}
";

assert_eq!(
Config::builder()
.override_with(Json5Source::new(config))
.try_build()
.expect("Failed to build config"),
Config {
message: "hello world".to_string(),
n: 42,
},
);
}
}
3 changes: 3 additions & 0 deletions confik/src/sources/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ pub(crate) mod file_source;
#[cfg(feature = "toml")]
pub(crate) mod toml_source;

#[cfg(feature = "json5")]
pub(crate) mod json5_source;

#[cfg(feature = "json")]
pub(crate) mod json_source;

Expand Down

0 comments on commit dfa6659

Please sign in to comment.