Compare commits
No commits in common. "0bd39a308c02915da3840bd271a57cff44420de0" and "75a99679a20ee277326c4dbf1ef13f31cc34faf4" have entirely different histories.
0bd39a308c
...
75a99679a2
8 changed files with 20 additions and 166 deletions
17
Cargo.toml
17
Cargo.toml
|
@ -3,21 +3,20 @@ name = "git-config"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Edward Shen <code@eddie.sh>"]
|
authors = ["Edward Shen <code@eddie.sh>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
exclude = ["fuzz/**/*", ".vscode/**/*"]
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[features]
|
|
||||||
serde = ["serde_crate"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
nom = "6"
|
||||||
bstr = "0.2.15"
|
bstr = "0.2.15"
|
||||||
nom = { version = "6", default_features = false, features = ["std"] }
|
|
||||||
serde_crate = { version = "1", package = "serde", optional = true}
|
[dependencies.serde_crate]
|
||||||
|
package = "serde"
|
||||||
|
optional = true
|
||||||
|
version = " 1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
|
||||||
[profile.release]
|
[features]
|
||||||
lto = true
|
serde = ["serde_crate"]
|
||||||
codegen-units = 1
|
|
||||||
|
|
4
fuzz/.gitignore
vendored
4
fuzz/.gitignore
vendored
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
target
|
|
||||||
corpus
|
|
||||||
artifacts
|
|
|
@ -1,26 +0,0 @@
|
||||||
|
|
||||||
[package]
|
|
||||||
name = "git-config-fuzz"
|
|
||||||
version = "0.0.0"
|
|
||||||
authors = ["Automatically generated"]
|
|
||||||
publish = false
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[package.metadata]
|
|
||||||
cargo-fuzz = true
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
libfuzzer-sys = "0.3"
|
|
||||||
|
|
||||||
[dependencies.git-config]
|
|
||||||
path = ".."
|
|
||||||
|
|
||||||
# Prevent this from interfering with workspaces
|
|
||||||
[workspace]
|
|
||||||
members = ["."]
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "parser"
|
|
||||||
path = "fuzz_targets/parser.rs"
|
|
||||||
test = false
|
|
||||||
doc = false
|
|
|
@ -1,8 +0,0 @@
|
||||||
#![no_main]
|
|
||||||
|
|
||||||
use git_config::parser::Parser;
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
|
||||||
|
|
||||||
fuzz_target!(|data: &[u8]| {
|
|
||||||
Parser::from_bytes(data);
|
|
||||||
});
|
|
|
@ -200,7 +200,7 @@ impl<'a> GitConfig<'a> {
|
||||||
/// `d`, since the last valid config value is `a = d`:
|
/// `d`, since the last valid config value is `a = d`:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use git_config::config::GitConfig;
|
/// # use serde_git_config::config::GitConfig;
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # let git_config = GitConfig::from_str("[core]a=b\n[core]\na=c\na=d").unwrap();
|
/// # let git_config = GitConfig::from_str("[core]a=b\n[core]\na=c\na=d").unwrap();
|
||||||
/// assert_eq!(git_config.get_raw_value("core", None, "a"), Ok(&Cow::Borrowed("d".into())));
|
/// assert_eq!(git_config.get_raw_value("core", None, "a"), Ok(&Cow::Borrowed("d".into())));
|
||||||
|
@ -275,7 +275,7 @@ impl<'a> GitConfig<'a> {
|
||||||
/// `d`, since the last valid config value is `a = d`:
|
/// `d`, since the last valid config value is `a = d`:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use git_config::config::{GitConfig, GitConfigError};
|
/// # use serde_git_config::config::{GitConfig, GitConfigError};
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # use bstr::BStr;
|
/// # use bstr::BStr;
|
||||||
/// # let mut git_config = GitConfig::from_str("[core]a=b\n[core]\na=c\na=d").unwrap();
|
/// # let mut git_config = GitConfig::from_str("[core]a=b\n[core]\na=c\na=d").unwrap();
|
||||||
|
@ -354,7 +354,7 @@ impl<'a> GitConfig<'a> {
|
||||||
/// Attempting to get all values of `a` yields the following:
|
/// Attempting to get all values of `a` yields the following:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use git_config::config::GitConfig;
|
/// # use serde_git_config::config::GitConfig;
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # let git_config = GitConfig::from_str("[core]a=b\n[core]\na=c\na=d").unwrap();
|
/// # let git_config = GitConfig::from_str("[core]a=b\n[core]\na=c\na=d").unwrap();
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
|
@ -419,7 +419,7 @@ impl<'a> GitConfig<'a> {
|
||||||
/// Attempting to get all values of `a` yields the following:
|
/// Attempting to get all values of `a` yields the following:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use git_config::config::{GitConfig, GitConfigError};
|
/// # use serde_git_config::config::{GitConfig, GitConfigError};
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # use bstr::BStr;
|
/// # use bstr::BStr;
|
||||||
/// # let mut git_config = GitConfig::from_str("[core]a=b\n[core]\na=c\na=d").unwrap();
|
/// # let mut git_config = GitConfig::from_str("[core]a=b\n[core]\na=c\na=d").unwrap();
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
// Cargo.toml cannot have self-referential dependencies, so you can't just
|
|
||||||
// specify the actual serde crate when you define a feature called serde. We
|
|
||||||
// instead call the serde crate as serde_crate and then rename the crate to
|
|
||||||
// serde, to get around this in an intuitive manner.
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
extern crate serde_crate as serde;
|
extern crate serde_crate as serde;
|
||||||
|
|
||||||
// mod de;
|
// mod de;
|
||||||
// mod ser;
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
mod error;
|
mod error;
|
||||||
|
// mod ser;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod values;
|
pub mod values;
|
||||||
|
|
||||||
|
|
|
@ -249,7 +249,7 @@ impl<'a> From<nom::Err<NomError<&'a [u8]>>> for ParserError<'a> {
|
||||||
/// non-significant events that occur in addition to the ones you may expect:
|
/// non-significant events that occur in addition to the ones you may expect:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use git_config::parser::{Event, ParsedSectionHeader, parse_from_str};
|
/// # use serde_git_config::parser::{Event, ParsedSectionHeader, parse_from_str};
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # let section_header = ParsedSectionHeader {
|
/// # let section_header = ParsedSectionHeader {
|
||||||
/// # name: Cow::Borrowed("core".into()),
|
/// # name: Cow::Borrowed("core".into()),
|
||||||
|
@ -288,7 +288,7 @@ impl<'a> From<nom::Err<NomError<&'a [u8]>>> for ParserError<'a> {
|
||||||
/// which means that the corresponding event won't appear either:
|
/// which means that the corresponding event won't appear either:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use git_config::parser::{Event, ParsedSectionHeader, parse_from_str};
|
/// # use serde_git_config::parser::{Event, ParsedSectionHeader, parse_from_str};
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # use bstr::BStr;
|
/// # use bstr::BStr;
|
||||||
/// # let section_header = ParsedSectionHeader {
|
/// # let section_header = ParsedSectionHeader {
|
||||||
|
@ -323,7 +323,7 @@ impl<'a> From<nom::Err<NomError<&'a [u8]>>> for ParserError<'a> {
|
||||||
/// relevant event stream emitted is thus emitted as:
|
/// relevant event stream emitted is thus emitted as:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use git_config::parser::{Event, ParsedSectionHeader, parse_from_str};
|
/// # use serde_git_config::parser::{Event, ParsedSectionHeader, parse_from_str};
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # let section_header = ParsedSectionHeader {
|
/// # let section_header = ParsedSectionHeader {
|
||||||
/// # name: Cow::Borrowed("core".into()),
|
/// # name: Cow::Borrowed("core".into()),
|
||||||
|
@ -360,7 +360,7 @@ impl<'a> From<nom::Err<NomError<&'a [u8]>>> for ParserError<'a> {
|
||||||
/// split value accordingly:
|
/// split value accordingly:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use git_config::parser::{Event, ParsedSectionHeader, parse_from_str};
|
/// # use serde_git_config::parser::{Event, ParsedSectionHeader, parse_from_str};
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # let section_header = ParsedSectionHeader {
|
/// # let section_header = ParsedSectionHeader {
|
||||||
/// # name: Cow::Borrowed("some-section".into()),
|
/// # name: Cow::Borrowed("some-section".into()),
|
||||||
|
@ -391,9 +391,9 @@ pub struct Parser<'a> {
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
/// Attempt to zero-copy parse the provided `&str`. On success, returns a
|
/// Attempt to zero-copy parse the provided `&str`. On success, returns a
|
||||||
/// [`Parser`] that provides methods to accessing leading comments and
|
/// [`Parser`] that provides methods to accessing leading comments and sections
|
||||||
/// sections of a `git-config` file and can be converted into an iterator of
|
/// of a `git-config` file and can be converted into an iterator of [`Event`]
|
||||||
/// [`Event`] for higher level processing.
|
/// for higher level processing.
|
||||||
///
|
///
|
||||||
/// This function is identical to [`parse_from_str`].
|
/// This function is identical to [`parse_from_str`].
|
||||||
///
|
///
|
||||||
|
@ -406,20 +406,6 @@ impl<'a> Parser<'a> {
|
||||||
parse_from_str(s)
|
parse_from_str(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to zero-copy parse the provided bytes. On success, returns a
|
|
||||||
/// [`Parser`] that provides methods to accessing leading comments and
|
|
||||||
/// sections of a `git-config` file and can be converted into an iterator of
|
|
||||||
/// [`Event`] for higher level processing.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns an error if the string provided is not a valid `git-config`.
|
|
||||||
/// This generally is due to either invalid names or if there's extraneous
|
|
||||||
/// data succeeding valid `git-config` data.
|
|
||||||
pub fn from_bytes(s: impl Into<&'a BStr>) -> Result<Self, ParserError<'a>> {
|
|
||||||
parse_from_bytes(s.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the leading events (any comments, whitespace, or newlines before
|
/// Returns the leading events (any comments, whitespace, or newlines before
|
||||||
/// a section) from the parser. Consider [`Parser::take_frontmatter`] if
|
/// a section) from the parser. Consider [`Parser::take_frontmatter`] if
|
||||||
/// you need an owned copy only once. If that function was called, then this
|
/// you need an owned copy only once. If that function was called, then this
|
||||||
|
@ -485,20 +471,6 @@ impl<'a> Parser<'a> {
|
||||||
/// This generally is due to either invalid names or if there's extraneous
|
/// This generally is due to either invalid names or if there's extraneous
|
||||||
/// data succeeding valid `git-config` data.
|
/// data succeeding valid `git-config` data.
|
||||||
pub fn parse_from_str(input: &str) -> Result<Parser<'_>, ParserError> {
|
pub fn parse_from_str(input: &str) -> Result<Parser<'_>, ParserError> {
|
||||||
parse_from_bytes(input.as_bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempt to zero-copy parse the provided bytes. On success, returns a
|
|
||||||
/// [`Parser`] that provides methods to accessing leading comments and sections
|
|
||||||
/// of a `git-config` file and can be converted into an iterator of [`Event`]
|
|
||||||
/// for higher level processing.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns an error if the string provided is not a valid `git-config`.
|
|
||||||
/// This generally is due to either invalid names or if there's extraneous
|
|
||||||
/// data succeeding valid `git-config` data.
|
|
||||||
pub fn parse_from_bytes(input: &[u8]) -> Result<Parser<'_>, ParserError> {
|
|
||||||
let (i, frontmatter) = many0(alt((
|
let (i, frontmatter) = many0(alt((
|
||||||
map(comment, Event::Comment),
|
map(comment, Event::Comment),
|
||||||
map(take_spaces, |whitespace| {
|
map(take_spaces, |whitespace| {
|
||||||
|
|
|
@ -79,15 +79,6 @@ impl Display for Boolean<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<bool> for Boolean<'_> {
|
|
||||||
fn into(self) -> bool {
|
|
||||||
match self {
|
|
||||||
Boolean::True(_) => true,
|
|
||||||
Boolean::False(_) => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl Serialize for Boolean<'_> {
|
impl Serialize for Boolean<'_> {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
@ -592,72 +583,6 @@ impl FromStr for ColorAttribute {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod boolean {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn from_str_false() {
|
|
||||||
assert_eq!(
|
|
||||||
Boolean::from_str("no"),
|
|
||||||
Ok(Boolean::False(FalseVariant("no")))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Boolean::from_str("off"),
|
|
||||||
Ok(Boolean::False(FalseVariant("off")))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Boolean::from_str("false"),
|
|
||||||
Ok(Boolean::False(FalseVariant("false")))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Boolean::from_str("zero"),
|
|
||||||
Ok(Boolean::False(FalseVariant("zero")))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Boolean::from_str("\"\""),
|
|
||||||
Ok(Boolean::False(FalseVariant("\"\"")))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn from_str_true() {
|
|
||||||
assert_eq!(
|
|
||||||
Boolean::from_str("yes"),
|
|
||||||
Ok(Boolean::True(TrueVariant::Explicit("yes")))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Boolean::from_str("on"),
|
|
||||||
Ok(Boolean::True(TrueVariant::Explicit("on")))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Boolean::from_str("true"),
|
|
||||||
Ok(Boolean::True(TrueVariant::Explicit("true")))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Boolean::from_str("one"),
|
|
||||||
Ok(Boolean::True(TrueVariant::Explicit("one")))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ignores_case() {
|
|
||||||
// Random subset
|
|
||||||
for word in &["no", "yes", "off", "true", "zero"] {
|
|
||||||
let first: bool = Boolean::from_str(word).unwrap().into();
|
|
||||||
let second: bool = Boolean::from_str(&word.to_uppercase()).unwrap().into();
|
|
||||||
assert_eq!(first, second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn from_str_err() {
|
|
||||||
assert!(Boolean::from_str("yesn't").is_err());
|
|
||||||
assert!(Boolean::from_str("yesno").is_err());
|
|
||||||
assert!(Boolean::from_str("").is_err());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod integer {
|
mod integer {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Reference in a new issue