Part 5: parse edn::Value::Uuid.
This commit is contained in:
parent
58a310a6e1
commit
ab3600e288
6 changed files with 62 additions and 11 deletions
|
@ -15,6 +15,7 @@ itertools = "0.5.9"
|
|||
num = "0.1.35"
|
||||
ordered-float = "0.4.0"
|
||||
pretty = "0.2.0"
|
||||
uuid = "0.5.0"
|
||||
|
||||
[build-dependencies]
|
||||
peg = "0.5.1"
|
||||
|
|
|
@ -16,6 +16,7 @@ use std::f64::{NAN, INFINITY, NEG_INFINITY};
|
|||
|
||||
use num::BigInt;
|
||||
use ordered_float::OrderedFloat;
|
||||
use uuid::Uuid;
|
||||
|
||||
use types::{SpannedValue, Span, ValueAndSpan};
|
||||
|
||||
|
@ -142,6 +143,19 @@ pub text -> ValueAndSpan =
|
|||
}
|
||||
}
|
||||
|
||||
pub uuid_string -> Uuid =
|
||||
"\"" u:$( [a-f0-9]*<8> "-" [a-f0-9]*<4> "-" [a-f0-9]*<4> "-" [a-f0-9]*<4> "-" [a-f0-9]*<12> ) "\"" {
|
||||
Uuid::parse_str(u).expect("this is a valid UUID string")
|
||||
}
|
||||
|
||||
pub uuid -> ValueAndSpan =
|
||||
start:#position "#uuid" whitespace+ u:(uuid_string) end:#position {
|
||||
ValueAndSpan {
|
||||
inner: SpannedValue::Uuid(u),
|
||||
span: Span::new(start, end)
|
||||
}
|
||||
}
|
||||
|
||||
namespace_divider = "."
|
||||
namespace_separator = "/"
|
||||
|
||||
|
@ -220,7 +234,7 @@ pub map -> ValueAndSpan =
|
|||
// It's important that float comes before integer or the parser assumes that
|
||||
// floats are integers and fails to parse
|
||||
pub value -> ValueAndSpan =
|
||||
__ v:(nil / nan / infinity / boolean / float / octalinteger / hexinteger / basedinteger / bigint / integer / text / keyword / symbol / list / vector / map / set) __ {
|
||||
__ v:(nil / nan / infinity / boolean / float / octalinteger / hexinteger / basedinteger / uuid / bigint / integer / text / keyword / symbol / list / vector / map / set) __ {
|
||||
v
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ extern crate itertools;
|
|||
extern crate num;
|
||||
extern crate ordered_float;
|
||||
extern crate pretty;
|
||||
extern crate uuid;
|
||||
|
||||
pub mod symbols;
|
||||
pub mod types;
|
||||
|
@ -23,8 +24,12 @@ pub mod parse {
|
|||
include!(concat!(env!("OUT_DIR"), "/edn.rs"));
|
||||
}
|
||||
|
||||
// Re-export the types we use.
|
||||
pub use num::BigInt;
|
||||
pub use ordered_float::OrderedFloat;
|
||||
pub use uuid::Uuid;
|
||||
|
||||
// Export from our modules.
|
||||
pub use parse::ParseError;
|
||||
pub use types::{Span, SpannedValue, Value, ValueAndSpan};
|
||||
pub use symbols::{Keyword, NamespacedKeyword, PlainSymbol, NamespacedSymbol};
|
||||
|
|
|
@ -69,6 +69,7 @@ impl Value {
|
|||
Value::NamespacedKeyword(ref v) => pp.text(":").append(v.namespace.as_ref()).append("/").append(v.name.as_ref()),
|
||||
Value::Keyword(ref v) => pp.text(":").append(v.0.as_ref()),
|
||||
Value::Text(ref v) => pp.text("\"").append(v.as_ref()).append("\""),
|
||||
Value::Uuid(ref u) => pp.text("#uuid \"").append(u.hyphenated().to_string()).append("\""),
|
||||
_ => pp.text(self.to_string())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,11 @@ use std::cmp::{Ordering, Ord, PartialOrd};
|
|||
use std::fmt::{Display, Formatter};
|
||||
use std::f64;
|
||||
|
||||
use symbols;
|
||||
use num::BigInt;
|
||||
use ordered_float::OrderedFloat;
|
||||
use uuid::Uuid;
|
||||
|
||||
use symbols;
|
||||
|
||||
/// Value represents one of the allowed values in an EDN string.
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
||||
|
@ -28,6 +30,7 @@ pub enum Value {
|
|||
BigInteger(BigInt),
|
||||
Float(OrderedFloat<f64>),
|
||||
Text(String),
|
||||
Uuid(Uuid),
|
||||
PlainSymbol(symbols::PlainSymbol),
|
||||
NamespacedSymbol(symbols::NamespacedSymbol),
|
||||
Keyword(symbols::Keyword),
|
||||
|
@ -55,6 +58,7 @@ pub enum SpannedValue {
|
|||
BigInteger(BigInt),
|
||||
Float(OrderedFloat<f64>),
|
||||
Text(String),
|
||||
Uuid(Uuid),
|
||||
PlainSymbol(symbols::PlainSymbol),
|
||||
NamespacedSymbol(symbols::NamespacedSymbol),
|
||||
Keyword(symbols::Keyword),
|
||||
|
@ -126,6 +130,7 @@ impl From<SpannedValue> for Value {
|
|||
SpannedValue::BigInteger(v) => Value::BigInteger(v),
|
||||
SpannedValue::Float(v) => Value::Float(v),
|
||||
SpannedValue::Text(v) => Value::Text(v),
|
||||
SpannedValue::Uuid(v) => Value::Uuid(v),
|
||||
SpannedValue::PlainSymbol(v) => Value::PlainSymbol(v),
|
||||
SpannedValue::NamespacedSymbol(v) => Value::NamespacedSymbol(v),
|
||||
SpannedValue::Keyword(v) => Value::Keyword(v),
|
||||
|
@ -271,6 +276,7 @@ macro_rules! def_common_value_methods {
|
|||
def_is!(is_big_integer, $t::BigInteger(_));
|
||||
def_is!(is_float, $t::Float(_));
|
||||
def_is!(is_text, $t::Text(_));
|
||||
def_is!(is_uuid, $t::Uuid(_));
|
||||
def_is!(is_symbol, $t::PlainSymbol(_));
|
||||
def_is!(is_namespaced_symbol, $t::NamespacedSymbol(_));
|
||||
def_is!(is_keyword, $t::Keyword(_));
|
||||
|
@ -293,6 +299,7 @@ macro_rules! def_common_value_methods {
|
|||
def_as_ref!(as_big_integer, $t::BigInteger, BigInt);
|
||||
def_as_ref!(as_ordered_float, $t::Float, OrderedFloat<f64>);
|
||||
def_as_ref!(as_text, $t::Text, String);
|
||||
def_as_ref!(as_uuid, $t::Uuid, Uuid);
|
||||
def_as_ref!(as_symbol, $t::PlainSymbol, symbols::PlainSymbol);
|
||||
def_as_ref!(as_namespaced_symbol, $t::NamespacedSymbol, symbols::NamespacedSymbol);
|
||||
def_as_ref!(as_keyword, $t::Keyword, symbols::Keyword);
|
||||
|
@ -308,6 +315,7 @@ macro_rules! def_common_value_methods {
|
|||
def_into!(into_ordered_float, $t::Float, OrderedFloat<f64>,);
|
||||
def_into!(into_float, $t::Float, f64, |v: OrderedFloat<f64>| v.into_inner());
|
||||
def_into!(into_text, $t::Text, String,);
|
||||
def_into!(into_uuid, $t::Uuid, Uuid,);
|
||||
def_into!(into_symbol, $t::PlainSymbol, symbols::PlainSymbol,);
|
||||
def_into!(into_namespaced_symbol, $t::NamespacedSymbol, symbols::NamespacedSymbol,);
|
||||
def_into!(into_keyword, $t::Keyword, symbols::Keyword,);
|
||||
|
@ -337,14 +345,15 @@ macro_rules! def_common_value_methods {
|
|||
$t::BigInteger(_) => 3,
|
||||
$t::Float(_) => 4,
|
||||
$t::Text(_) => 5,
|
||||
$t::PlainSymbol(_) => 6,
|
||||
$t::NamespacedSymbol(_) => 7,
|
||||
$t::Keyword(_) => 8,
|
||||
$t::NamespacedKeyword(_) => 9,
|
||||
$t::Vector(_) => 10,
|
||||
$t::List(_) => 11,
|
||||
$t::Set(_) => 12,
|
||||
$t::Map(_) => 13,
|
||||
$t::Uuid(_) => 6,
|
||||
$t::PlainSymbol(_) => 7,
|
||||
$t::NamespacedSymbol(_) => 8,
|
||||
$t::Keyword(_) => 9,
|
||||
$t::NamespacedKeyword(_) => 10,
|
||||
$t::Vector(_) => 11,
|
||||
$t::List(_) => 12,
|
||||
$t::Set(_) => 13,
|
||||
$t::Map(_) => 14,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,6 +365,7 @@ macro_rules! def_common_value_methods {
|
|||
$t::BigInteger(_) => false,
|
||||
$t::Float(_) => false,
|
||||
$t::Text(_) => false,
|
||||
$t::Uuid(_) => false,
|
||||
$t::PlainSymbol(_) => false,
|
||||
$t::NamespacedSymbol(_) => false,
|
||||
$t::Keyword(_) => false,
|
||||
|
@ -392,6 +402,7 @@ macro_rules! def_common_value_ord {
|
|||
(&$t::BigInteger(ref a), &$t::BigInteger(ref b)) => b.cmp(a),
|
||||
(&$t::Float(ref a), &$t::Float(ref b)) => b.cmp(a),
|
||||
(&$t::Text(ref a), &$t::Text(ref b)) => b.cmp(a),
|
||||
(&$t::Uuid(ref a), &$t::Uuid(ref b)) => b.cmp(a),
|
||||
(&$t::PlainSymbol(ref a), &$t::PlainSymbol(ref b)) => b.cmp(a),
|
||||
(&$t::NamespacedSymbol(ref a), &$t::NamespacedSymbol(ref b)) => b.cmp(a),
|
||||
(&$t::Keyword(ref a), &$t::Keyword(ref b)) => b.cmp(a),
|
||||
|
@ -429,6 +440,7 @@ macro_rules! def_common_value_display {
|
|||
}
|
||||
// TODO: EDN escaping.
|
||||
$t::Text(ref v) => write!($f, "\"{}\"", v),
|
||||
$t::Uuid(ref u) => write!($f, "#uuid \"{}\"", u.hyphenated().to_string()),
|
||||
$t::PlainSymbol(ref v) => v.fmt($f),
|
||||
$t::NamespacedSymbol(ref v) => v.fmt($f),
|
||||
$t::Keyword(ref v) => v.fmt($f),
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
extern crate edn;
|
||||
extern crate num;
|
||||
extern crate ordered_float;
|
||||
extern crate uuid;
|
||||
|
||||
use std::collections::{BTreeSet, BTreeMap, LinkedList};
|
||||
use std::iter::FromIterator;
|
||||
|
@ -55,7 +56,7 @@ macro_rules! fn_parse_into_value {
|
|||
}
|
||||
|
||||
// These look exactly like their `parse::foo` counterparts, but
|
||||
// automatically convert the returned result into Value. Use `parse:foo`
|
||||
// automatically convert the returned result into Value. Use `parse::foo`
|
||||
// if you want the original ValueAndSpan instance.
|
||||
fn_parse_into_value!(nil);
|
||||
fn_parse_into_value!(nan);
|
||||
|
@ -242,6 +243,23 @@ fn test_span_integer() {
|
|||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uuid() {
|
||||
assert!(parse::uuid("#uuid \"z50e8400-e29b-41d4-a716-446655440000\"").is_err()); // Not hex.
|
||||
assert!(parse::uuid("\"z50e8400-e29b-41d4-a716-446655440000\"").is_err()); // No tag.
|
||||
assert!(parse::uuid("#uuid \"aaaaaaaae29b-41d4-a716-446655440000\"").is_err()); // Hyphens.
|
||||
assert!(parse::uuid("#uuid \"aaaaaaaa-e29b-41d4-a716-446655440\"").is_err()); // Truncated.
|
||||
assert!(parse::uuid("#uuid \"A50e8400-e29b-41d4-a716-446655440000\"").is_err()); // Capital.
|
||||
|
||||
let expected = uuid::Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000")
|
||||
.expect("valid UUID");
|
||||
let actual = parse::uuid("#uuid \"550e8400-e29b-41d4-a716-446655440000\"")
|
||||
.expect("parse success")
|
||||
.inner
|
||||
.into();
|
||||
assert_eq!(self::Value::Uuid(expected), actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bigint() {
|
||||
use self::Value::*;
|
||||
|
|
Loading…
Reference in a new issue