Use traits instead of shadowing from_str
This commit is contained in:
parent
781040a88b
commit
a50544b43a
4 changed files with 46 additions and 24 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -3,6 +3,7 @@
|
||||||
"Multivar",
|
"Multivar",
|
||||||
"autocrlf",
|
"autocrlf",
|
||||||
"bstr",
|
"bstr",
|
||||||
|
"combinator",
|
||||||
"gitea",
|
"gitea",
|
||||||
"gpgsign",
|
"gpgsign",
|
||||||
"implicits",
|
"implicits",
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
|
//! # git_config
|
||||||
|
//!
|
||||||
|
//! This crate is a high performance `git-config` file reader and writer. It
|
||||||
|
//! exposes a high level API to parse, read, and write [`git-config` files],
|
||||||
|
//! which are loosely based on the [INI file format].
|
||||||
|
//!
|
||||||
|
//! [`git-config` files]: https://git-scm.com/docs/git-config#_configuration_file
|
||||||
|
//! [INI file format]: https://en.wikipedia.org/wiki/INI_file
|
||||||
|
|
||||||
// Cargo.toml cannot have self-referential dependencies, so you can't just
|
// 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
|
// 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
|
// instead call the serde crate as serde_crate and then rename the crate to
|
||||||
|
|
|
@ -790,6 +790,13 @@ fn config_value<'a, 'b>(i: &'a [u8], events: &'b mut Vec<Event<'a>>) -> IResult<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles parsing of known-to-be values. This function handles both single
|
||||||
|
/// line values as well as values that are continuations.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if an invalid escape was used, if there was an unfinished
|
||||||
|
/// quote, or there was an escape but there is nothing left to escape.
|
||||||
fn value_impl<'a, 'b>(i: &'a [u8], events: &'b mut Vec<Event<'a>>) -> IResult<&'a [u8], ()> {
|
fn value_impl<'a, 'b>(i: &'a [u8], events: &'b mut Vec<Event<'a>>) -> IResult<&'a [u8], ()> {
|
||||||
let mut parsed_index: usize = 0;
|
let mut parsed_index: usize = 0;
|
||||||
let mut offset: usize = 0;
|
let mut offset: usize = 0;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Rust containers for valid `git-config` types.
|
//! Rust containers for valid `git-config` types.
|
||||||
|
|
||||||
use std::{borrow::Cow, fmt::Display, str::FromStr};
|
use std::{borrow::Cow, convert::TryFrom, fmt::Display, str::FromStr};
|
||||||
|
|
||||||
use bstr::BStr;
|
use bstr::BStr;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
|
@ -27,7 +27,7 @@ impl<'a> Value<'a> {
|
||||||
|
|
||||||
impl<'a> From<&'a str> for Value<'a> {
|
impl<'a> From<&'a str> for Value<'a> {
|
||||||
fn from(s: &'a str) -> Self {
|
fn from(s: &'a str) -> Self {
|
||||||
if let Ok(bool) = Boolean::from_str(s) {
|
if let Ok(bool) = Boolean::try_from(s) {
|
||||||
return Self::Boolean(bool);
|
return Self::Boolean(bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,9 +66,11 @@ pub enum Boolean<'a> {
|
||||||
False(&'a str),
|
False(&'a str),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Boolean<'a> {
|
impl<'a> TryFrom<&'a str> for Boolean<'a> {
|
||||||
pub fn from_str(value: &'a str) -> Result<Self, ()> {
|
type Error = ();
|
||||||
if let Ok(v) = TrueVariant::from_str(value) {
|
|
||||||
|
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
|
||||||
|
if let Ok(v) = TrueVariant::try_from(value) {
|
||||||
return Ok(Self::True(v));
|
return Ok(Self::True(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +91,7 @@ impl Display for Boolean<'_> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Boolean::True(v) => v.fmt(f),
|
Boolean::True(v) => v.fmt(f),
|
||||||
Boolean::False(v) => v.fmt(f),
|
Boolean::False(v) => write!(f, "{}", v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,8 +128,10 @@ pub enum TrueVariant<'a> {
|
||||||
Implicit,
|
Implicit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TrueVariant<'a> {
|
impl<'a> TryFrom<&'a str> for TrueVariant<'a> {
|
||||||
pub fn from_str(value: &'a str) -> Result<TrueVariant<'a>, ()> {
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
|
||||||
if value.eq_ignore_ascii_case("yes")
|
if value.eq_ignore_ascii_case("yes")
|
||||||
|| value.eq_ignore_ascii_case("on")
|
|| value.eq_ignore_ascii_case("on")
|
||||||
|| value.eq_ignore_ascii_case("true")
|
|| value.eq_ignore_ascii_case("true")
|
||||||
|
@ -221,14 +225,15 @@ impl FromStr for Integer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
|
||||||
enum IntegerSuffix {
|
pub enum IntegerSuffix {
|
||||||
Kilo,
|
Kilo,
|
||||||
Mega,
|
Mega,
|
||||||
Giga,
|
Giga,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntegerSuffix {
|
impl IntegerSuffix {
|
||||||
fn bitwise_offset(&self) -> usize {
|
/// Returns the number of bits that the suffix shifts left by.
|
||||||
|
pub fn bitwise_offset(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Self::Kilo => 10,
|
Self::Kilo => 10,
|
||||||
Self::Mega => 20,
|
Self::Mega => 20,
|
||||||
|
@ -579,29 +584,29 @@ mod boolean {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_str_false() {
|
fn from_str_false() {
|
||||||
assert_eq!(Boolean::from_str("no"), Ok(Boolean::False("no")));
|
assert_eq!(Boolean::try_from("no"), Ok(Boolean::False("no")));
|
||||||
assert_eq!(Boolean::from_str("off"), Ok(Boolean::False("off")));
|
assert_eq!(Boolean::try_from("off"), Ok(Boolean::False("off")));
|
||||||
assert_eq!(Boolean::from_str("false"), Ok(Boolean::False("false")));
|
assert_eq!(Boolean::try_from("false"), Ok(Boolean::False("false")));
|
||||||
assert_eq!(Boolean::from_str("zero"), Ok(Boolean::False("zero")));
|
assert_eq!(Boolean::try_from("zero"), Ok(Boolean::False("zero")));
|
||||||
assert_eq!(Boolean::from_str("\"\""), Ok(Boolean::False("\"\"")));
|
assert_eq!(Boolean::try_from("\"\""), Ok(Boolean::False("\"\"")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_str_true() {
|
fn from_str_true() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Boolean::from_str("yes"),
|
Boolean::try_from("yes"),
|
||||||
Ok(Boolean::True(TrueVariant::Explicit("yes")))
|
Ok(Boolean::True(TrueVariant::Explicit("yes")))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Boolean::from_str("on"),
|
Boolean::try_from("on"),
|
||||||
Ok(Boolean::True(TrueVariant::Explicit("on")))
|
Ok(Boolean::True(TrueVariant::Explicit("on")))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Boolean::from_str("true"),
|
Boolean::try_from("true"),
|
||||||
Ok(Boolean::True(TrueVariant::Explicit("true")))
|
Ok(Boolean::True(TrueVariant::Explicit("true")))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Boolean::from_str("one"),
|
Boolean::try_from("one"),
|
||||||
Ok(Boolean::True(TrueVariant::Explicit("one")))
|
Ok(Boolean::True(TrueVariant::Explicit("one")))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -610,17 +615,17 @@ mod boolean {
|
||||||
fn ignores_case() {
|
fn ignores_case() {
|
||||||
// Random subset
|
// Random subset
|
||||||
for word in &["no", "yes", "off", "true", "zero"] {
|
for word in &["no", "yes", "off", "true", "zero"] {
|
||||||
let first: bool = Boolean::from_str(word).unwrap().into();
|
let first: bool = Boolean::try_from(*word).unwrap().into();
|
||||||
let second: bool = Boolean::from_str(&word.to_uppercase()).unwrap().into();
|
let second: bool = Boolean::try_from(&*word.to_uppercase()).unwrap().into();
|
||||||
assert_eq!(first, second);
|
assert_eq!(first, second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_str_err() {
|
fn from_str_err() {
|
||||||
assert!(Boolean::from_str("yesn't").is_err());
|
assert!(Boolean::try_from("yesn't").is_err());
|
||||||
assert!(Boolean::from_str("yesno").is_err());
|
assert!(Boolean::try_from("yesno").is_err());
|
||||||
assert!(Boolean::from_str("").is_err());
|
assert!(Boolean::try_from("").is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue