From e2587c2648eccb0f289e037c877f5e97801a778d Mon Sep 17 00:00:00 2001 From: Ivan Ukhov Date: Thu, 14 Nov 2024 10:36:22 +0100 Subject: [PATCH] Clean the repository --- .github/workflows/build.yml | 29 ++++++ .travis.yml | 10 -- Cargo.toml | 15 +-- README.md | 40 ++------ src/format/mod.rs | 7 -- src/format/toml.rs | 73 -------------- src/lib.rs | 50 +--------- src/node.rs | 64 ------------ src/result.rs | 28 ------ src/tree.rs | 187 ------------------------------------ 10 files changed, 40 insertions(+), 463 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 .travis.yml delete mode 100644 src/format/mod.rs delete mode 100644 src/format/toml.rs delete mode 100644 src/node.rs delete mode 100644 src/result.rs delete mode 100644 src/tree.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..dd76dff --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,29 @@ +name: build + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + check: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - run: rustup toolchain install stable --profile=minimal --component clippy --component rustfmt + - run: cargo clippy --all-features -- -D warnings + - run: cargo fmt --all -- --check + + test: + strategy: + matrix: + os: [macos-latest, ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - run: rustup toolchain install stable --profile=minimal + - run: cargo test --all-features diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f5f5deb..0000000 --- a/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: rust -sudo: false - -rust: - - stable - - beta - - nightly - -notifications: - email: false diff --git a/Cargo.toml b/Cargo.toml index ee8b3df..b64ae6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,20 +1,9 @@ [package] name = "configuration" -version = "0.7.2" +version = "0.8.0" license = "Apache-2.0/MIT" authors = ["Ivan Ukhov "] -description = "The package provides a malleable tree structure." +description = "The package provides a means of configuration." documentation = "https://docs.rs/configuration" homepage = "https://github.com/stainless-steel/configuration" repository = "https://github.com/stainless-steel/configuration" - -[features] -default = ["toml"] - -[dependencies] -options = "0.5" - -[dependencies.toml] -version = "0.1" -optional = true -default-features = false diff --git a/README.md b/README.md index 4e39323..d10adbb 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,6 @@ -# Configuration [![Version][version-img]][version-url] [![Status][status-img]][status-url] +# Configuration [![Package][package-img]][package-url] [![Documentation][documentation-img]][documentation-url] [![Build][build-img]][build-url] -The package provides a malleable tree structure. - -## [Documentation][documentation] - -## Example - -```rust -let tree = configuration::format::TOML::parse(r#" - message = "one" - - [foo.bar] - message = "two" - - [foo.baz] - answer = 42 -"#).unwrap(); - -assert_eq!(tree.get::("message").unwrap(), "one"); -assert_eq!(tree.get::("foo.message").unwrap(), "one"); -assert_eq!(tree.get::("foo.bar.message").unwrap(), "two"); -assert_eq!(tree.get::("foo.baz.message").unwrap(), "one"); - -let tree = tree.branch("foo.baz").unwrap(); - -assert_eq!(tree.get::("answer").unwrap(), &42); -``` +The package provides a means of configuration. ## Contribution @@ -33,8 +8,9 @@ Your contribution is highly appreciated. Do not hesitate to open an issue or a pull request. Note that any contribution submitted for inclusion in the project will be licensed according to the terms given in [LICENSE.md](LICENSE.md). -[documentation]: https://docs.rs/configuration -[status-img]: https://travis-ci.org/stainless-steel/configuration.svg?branch=master -[status-url]: https://travis-ci.org/stainless-steel/configuration -[version-img]: https://img.shields.io/crates/v/configuration.svg -[version-url]: https://crates.io/crates/configuration +[build-img]: https://github.com/stainless-steel/configuration/workflows/build/badge.svg +[build-url]: https://github.com/stainless-steel/configuration/actions/workflows/build.yml +[documentation-img]: https://docs.rs/configuration/badge.svg +[documentation-url]: https://docs.rs/configuration +[package-img]: https://img.shields.io/crates/v/configuration.svg +[package-url]: https://crates.io/crates/configuration diff --git a/src/format/mod.rs b/src/format/mod.rs deleted file mode 100644 index 8fd8dab..0000000 --- a/src/format/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! File formats. - -#[cfg(feature = "toml")] -mod toml; - -#[cfg(feature = "toml")] -pub use self::toml::TOML; diff --git a/src/format/toml.rs b/src/format/toml.rs deleted file mode 100644 index 0c17ece..0000000 --- a/src/format/toml.rs +++ /dev/null @@ -1,73 +0,0 @@ -use options::Options; -use std::path::Path; -use toml::{Array, Parser, Table, Value}; - -use {Node, Result, Tree}; - -/// The TOML format. -pub struct TOML; - -impl TOML { - /// Open a file. - pub fn open>(path: T) -> Result { - use std::fs::File; - use std::io::Read; - - let mut content = String::new(); - ok!(ok!(File::open(path)).read_to_string(&mut content)); - TOML::parse(&content) - } - - /// Parse a text. - pub fn parse(content: &str) -> Result { - let mut parser = Parser::new(content); - match parser.parse() { - Some(table) => Ok(Tree::from(try!(convert_table(table)))), - _ => raise!("failed to parse ({})", collect_errors(&parser)), - } - } -} - -fn convert_array(array: Array) -> Result> { - let mut nodes = vec![]; - for value in array { - if let Value::Table(inner) = value { - nodes.push(try!(convert_table(inner))); - } else { - raise!("expected a table"); - } - } - Ok(nodes) -} - -fn convert_table(mut table: Table) -> Result { - let mut options = Options::new(); - - for (name, _) in &table { - options.set(name, 0); - } - for (name, value) in &mut options { - match table.remove(name).unwrap() { - Value::Array(inner) => value.set(try!(convert_array(inner))), - Value::Boolean(inner) => value.set(inner), - Value::Datetime(inner) => value.set(inner), - Value::Float(inner) => value.set(inner), - Value::Integer(inner) => value.set(inner), - Value::String(inner) => value.set(inner), - Value::Table(inner) => value.set(try!(convert_table(inner))), - } - } - - Ok(Node::from(options)) -} - -fn collect_errors(parser: &Parser) -> String { - let mut errors = String::new(); - for error in parser.errors.iter() { - if !errors.is_empty() { - errors.push_str(", "); - } - errors.push_str(&format!("{}", error)); - } - errors -} diff --git a/src/lib.rs b/src/lib.rs index 7cd12b2..a28d3cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,49 +1 @@ -//! Malleable tree structure. -//! -//! ``` -//! let tree = configuration::format::TOML::parse(r#" -//! message = "one" -//! -//! [foo.bar] -//! message = "two" -//! -//! [foo.baz] -//! answer = 42 -//! "#).unwrap(); -//! -//! assert_eq!(tree.get::("message").unwrap(), "one"); -//! assert_eq!(tree.get::("foo.message").unwrap(), "one"); -//! assert_eq!(tree.get::("foo.bar.message").unwrap(), "two"); -//! assert_eq!(tree.get::("foo.baz.message").unwrap(), "one"); -//! -//! let tree = tree.branch("foo.baz").unwrap(); -//! -//! assert_eq!(tree.get::("answer").unwrap(), &42); -//! ``` - -extern crate options; - -#[cfg(feature = "toml")] -extern crate toml; - -macro_rules! ok( - ($result:expr) => (match $result { - Ok(result) => result, - Err(error) => raise!(error), - }); -); - -macro_rules! raise( - ($message:expr) => (return Err(::Error($message.to_string()))); - ($($argument:tt)*) => (return Err(::Error(format!($($argument)*)))); -); - -pub mod format; - -mod node; -mod result; -mod tree; - -pub use node::Node; -pub use result::{Error, Result}; -pub use tree::Tree; +//! Means of configuration. diff --git a/src/node.rs b/src/node.rs deleted file mode 100644 index 8340b17..0000000 --- a/src/node.rs +++ /dev/null @@ -1,64 +0,0 @@ -use options::Options; -use std::any::Any; - -/// A node. -#[derive(Debug)] -pub struct Node(Options); - -impl Node { - /// Create a node. - #[inline] - pub fn new() -> Node { - Node(Options::new()) - } - - /// Read a value. - pub fn get<'l, T: Any>(&'l self, path: &str) -> Option<&'l T> { - let (head, tail) = match path.find('.') { - Some(i) => (&path[..i], &path[(i + 1)..]), - _ => return self.0.get_ref(path), - }; - if let Some(node) = self.0.get_ref::(head) { - return node.get(tail); - } - if let Some(array) = self.0.get_ref::>(head) { - let (head, tail) = match tail.find('.') { - Some(i) => (&tail[..i], &tail[(i + 1)..]), - _ => (tail, ""), - }; - if let Ok(i) = head.parse::() { - if tail.is_empty() { - return Any::downcast_ref(&array[i]); - } else { - return array[i].get(tail); - } - } - } - None - } - - /// Write a value. - pub fn set(&mut self, path: &str, value: T) -> Option<()> { - let (head, tail) = match path.find('.') { - Some(i) => (&path[..i], &path[(i + 1)..]), - _ => { - self.0.set(path, value); - return Some(()); - }, - }; - if let Some(node) = self.0.get_mut::(head) { - return node.set(tail, value); - } - let mut node = Node(Options::new()); - let result = node.set(tail, value); - self.0.set(head, node); - result - } -} - -impl From for Node { - #[inline] - fn from(options: Options) -> Node { - Node(options) - } -} diff --git a/src/result.rs b/src/result.rs deleted file mode 100644 index 01f52c2..0000000 --- a/src/result.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::{error, fmt, result}; - -/// An error. -pub struct Error(pub String); - -/// A result. -pub type Result = result::Result; - -impl error::Error for Error { - #[inline] - fn description(&self) -> &str { - &self.0 - } -} - -impl fmt::Debug for Error { - #[inline] - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(formatter) - } -} - -impl fmt::Display for Error { - #[inline] - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(formatter) - } -} diff --git a/src/tree.rs b/src/tree.rs deleted file mode 100644 index b2f4725..0000000 --- a/src/tree.rs +++ /dev/null @@ -1,187 +0,0 @@ -use options::Options; -use std::any::Any; -use std::rc::Rc; - -use Node; - -/// A tree. -#[derive(Debug)] -pub struct Tree { - node: Rc, - path: String, -} - -impl Tree { - /// Create a tree. - #[inline] - pub fn new() -> Tree { - Tree { node: Rc::new(Node::new()), path: String::new() } - } - - /// Return a subtree. - pub fn branch(&self, path: &str) -> Option { - let path = self.chain(path); - if self.node.get::(&path).is_none() { - return None; - } - Some(Tree { - node: self.node.clone(), - path: path, - }) - } - - /// Return an array of subtrees. - pub fn forest(&self, path: &str) -> Option> { - let path = self.chain(path); - let array = match self.node.get::>(&path) { - Some(array) => array, - _ => return None, - }; - Some(array.iter().enumerate().map(|(i, _)| { - Tree { - node: self.node.clone(), - path: format!("{}.{}", path, i), - } - }).collect()) - } - - /// Read a value. - pub fn get<'l, T: Any>(&'l self, path: &str) -> Option<&'l T> { - let (head, tail) = match path.rfind('.') { - Some(i) => (self.chain(&path[..i]), &path[(i + 1)..]), - _ => (self.path.clone(), path), - }; - let mut head = &*head; - loop { - if head.is_empty() { - return self.node.get(tail); - } - if let Some(value) = self.node.get(&format!("{}.{}", head, tail)) { - return Some(value); - } - head = match head.rfind('.') { - Some(i) => &head[..i], - _ => "", - }; - } - } - - /// Write a value. - pub fn set(&mut self, path: &str, value: T) -> Option<()> { - let path = self.chain(path); - match Rc::get_mut(&mut self.node) { - Some(node) => node.set(&path, value), - _ => None, - } - } - - fn chain(&self, chunk: &str) -> String { - if self.path.is_empty() { - return chunk.to_string(); - } - let mut path = self.path.clone(); - path.push('.'); - path.push_str(chunk); - path - } -} - -impl Clone for Tree { - fn clone(&self) -> Self { - Tree { node: self.node.clone(), path: self.path.clone(), } - } -} - -impl From for Tree { - fn from(options: Options) -> Tree { - Tree { node: Rc::new(Node::from(options)), path: String::new() } - } -} - -impl From for Tree { - fn from(node: Node) -> Tree { - Tree { node: Rc::new(node), path: String::new() } - } -} - -#[cfg(test)] -mod tests { - use format::TOML; - - #[test] - fn branch() { - let tree = TOML::parse(r#" - qux = 69 - - [foo] - bar = 42 - - [[bar.baz]] - qux = 42 - "#).unwrap(); - - { - let tree = tree.branch("foo").unwrap(); - assert_eq!(tree.get::("bar").unwrap(), &42); - assert_eq!(tree.get::("qux").unwrap(), &69); - } - { - let tree = tree.branch("bar").unwrap(); - assert_eq!(tree.get::("qux").unwrap(), &69); - } - { - let tree = tree.branch("bar.baz.0").unwrap(); - assert_eq!(tree.get::("qux").unwrap(), &42); - } - } - - #[test] - fn forest() { - let tree = TOML::parse(r#" - [[foo.bar]] - baz = 42 - - [[foo.bar]] - baz = 69 - "#).unwrap(); - - let baz = tree.forest("foo.bar").unwrap().iter().map(|tree| { - *tree.get::("baz").unwrap() - }).collect::>(); - - assert_eq!(&baz, &[42, 69]); - } - - #[test] - fn get() { - let tree = TOML::parse(r#" - qux = 69 - - [foo] - bar = 42 - "#).unwrap(); - - assert_eq!(tree.get::("qux").unwrap(), &69); - assert_eq!(tree.get::("foo.bar").unwrap(), &42); - assert_eq!(tree.get::("foo.qux").unwrap(), &69); - } - - #[test] - fn set() { - let mut tree = TOML::parse(r#" - qux = 69 - - [foo] - bar = 42 - "#).unwrap(); - - tree.set("qux", 42).unwrap(); - assert_eq!(tree.get::("qux").unwrap(), &42); - - tree.set("foo.bar", 69).unwrap(); - assert_eq!(tree.get::("foo.bar").unwrap(), &69); - - tree.set("foo.bar.baz", 42).unwrap(); - assert_eq!(tree.get::("foo.bar.baz").unwrap(), &42); - } -}