mod any_ref;
mod list;
mod map;
mod record;
mod set;
mod tuple;
use std::{
cmp::{
Eq,
Ordering::{self, *},
},
collections::{HashMap, HashSet},
convert::{TryFrom, TryInto},
fmt,
hash::{Hash, Hasher},
iter::FromIterator,
ptr,
sync::Arc,
};
use cirru_parser::Cirru;
pub use self::tuple::EdnTupleView;
pub use any_ref::{DynEq, EdnAnyRef};
pub use list::EdnListView;
pub use map::EdnMapView;
pub use record::EdnRecordView;
pub use set::EdnSetView;
use crate::tag::EdnTag;
#[derive(fmt::Debug, Clone)]
pub enum Edn {
Nil,
Bool(bool),
Number(f64),
Symbol(Arc<str>),
Tag(EdnTag),
Str(Arc<str>), Quote(Cirru),
Tuple(EdnTupleView),
List(EdnListView),
Set(EdnSetView),
Map(EdnMapView),
Record(EdnRecordView),
Buffer(Vec<u8>),
AnyRef(EdnAnyRef),
}
impl fmt::Display for Edn {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Nil => f.write_str("nil"),
Self::Bool(v) => f.write_fmt(format_args!("{}", v)),
Self::Number(n) => f.write_fmt(format_args!("{}", n)),
Self::Symbol(s) => f.write_fmt(format_args!("'{}", s)),
Self::Tag(s) => f.write_fmt(format_args!(":{}", s)),
Self::Str(s) => {
if is_simple_token(s) {
f.write_fmt(format_args!("|{}", s))
} else {
f.write_fmt(format_args!("\"|{}\"", s))
}
}
Self::Quote(v) => f.write_fmt(format_args!("(quote {})", v)),
Self::Tuple(EdnTupleView { tag, extra }) => {
let mut extra_str = String::new();
for item in extra {
extra_str.push(' ');
extra_str.push_str(&item.to_string());
}
f.write_fmt(format_args!("(:: {tag}{extra_str})"))
}
Self::List(EdnListView(xs)) => {
f.write_str("([]")?;
for x in xs {
f.write_fmt(format_args!(" {}", x))?;
}
f.write_str(")")
}
Self::Set(xs) => {
f.write_str("(#{}")?;
for x in &xs.0 {
f.write_fmt(format_args!(" {}", x))?;
}
f.write_str(")")
}
Self::Map(xs) => {
f.write_str("({}")?;
for (k, v) in &xs.0 {
f.write_fmt(format_args!(" ({} {})", k, v))?;
}
f.write_str(")")
}
Self::Record(EdnRecordView {
tag: name,
pairs: entries,
}) => {
f.write_fmt(format_args!("(%{{}} :{}", name))?;
for entry in entries {
f.write_fmt(format_args!(" ({} {})", Edn::Tag(entry.0.to_owned()), entry.1))?;
}
f.write_str(")")
}
Self::Buffer(buf) => {
f.write_str("(buf")?;
for b in buf {
f.write_str(" ")?;
f.write_str(&hex::encode(vec![*b]))?;
}
f.write_str(")")
}
Self::AnyRef(_r) => f.write_str("(any-ref ...)"),
}
}
}
fn is_simple_token(tok: &str) -> bool {
for s in tok.bytes() {
if !matches!(s, b'0'..=b'9' | b'A'..=b'Z'| b'a'..=b'z'| b'-' | b'?' | b'.'| b'$' | b',') {
return false;
}
}
true
}
impl Hash for Edn {
fn hash<H>(&self, _state: &mut H)
where
H: Hasher,
{
match self {
Self::Nil => "nil:".hash(_state),
Self::Bool(v) => {
"bool:".hash(_state);
v.hash(_state);
}
Self::Number(n) => {
"number:".hash(_state);
(*n as usize).hash(_state) }
Self::Symbol(s) => {
"symbol:".hash(_state);
s.hash(_state);
}
Self::Tag(s) => {
"tag:".hash(_state);
s.hash(_state);
}
Self::Str(s) => {
"string:".hash(_state);
s.hash(_state);
}
Self::Quote(v) => {
"quote:".hash(_state);
v.hash(_state);
}
Self::Tuple(EdnTupleView { tag: pair, extra }) => {
"tuple".hash(_state);
pair.hash(_state);
extra.hash(_state);
}
Self::List(v) => {
"list:".hash(_state);
v.hash(_state);
}
Self::Set(v) => {
"set:".hash(_state);
for x in &v.0 {
x.hash(_state)
}
}
Self::Map(v) => {
"map:".hash(_state);
for x in &v.0 {
x.hash(_state)
}
}
Self::Record(EdnRecordView {
tag: name,
pairs: entries,
}) => {
"record:".hash(_state);
name.hash(_state);
entries.hash(_state);
}
Self::Buffer(buf) => {
"buffer:".hash(_state);
for b in buf {
b.hash(_state);
}
}
Self::AnyRef(h) => {
"any-ref:".hash(_state);
ptr::hash(h, _state);
}
}
}
}
impl Ord for Edn {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(Self::Nil, Self::Nil) => Equal,
(Self::Nil, _) => Less,
(_, Self::Nil) => Greater,
(Self::Bool(a), Self::Bool(b)) => a.cmp(b),
(Self::Bool(_), _) => Less,
(_, Self::Bool(_)) => Greater,
(Self::Number(a), Self::Number(b)) => {
if a < b {
Less
} else if a > b {
Greater
} else {
Equal
}
}
(Self::Number(_), _) => Less,
(_, Self::Number(_)) => Greater,
(Self::Symbol(a), Self::Symbol(b)) => a.cmp(b),
(Self::Symbol(_), _) => Less,
(_, Self::Symbol(_)) => Greater,
(Self::Tag(a), Self::Tag(b)) => a.cmp(b),
(Self::Tag(_), _) => Less,
(_, Self::Tag(_)) => Greater,
(Self::Str(a), Self::Str(b)) => a.cmp(b),
(Self::Str(_), _) => Less,
(_, Self::Str(_)) => Greater,
(Self::Quote(a), Self::Quote(b)) => a.cmp(b),
(Self::Quote(_), _) => Less,
(_, Self::Quote(_)) => Greater,
(Self::Tuple(a), Self::Tuple(b)) => a.cmp(b),
(Self::Tuple(..), _) => Less,
(_, Self::Tuple(..)) => Greater,
(Self::List(a), Self::List(b)) => a.cmp(b),
(Self::List(_), _) => Less,
(_, Self::List(_)) => Greater,
(Self::Buffer(a), Self::Buffer(b)) => a.cmp(b),
(Self::Buffer(_), _) => Less,
(_, Self::Buffer(_)) => Greater,
(Self::Set(a), Self::Set(b)) => match a.len().cmp(&b.len()) {
Equal => unreachable!("TODO sets are not cmp ed"), a => a,
},
(Self::Set(_), _) => Less,
(_, Self::Set(_)) => Greater,
(Self::Map(a), Self::Map(b)) => {
match a.len().cmp(&b.len()) {
Equal => unreachable!("TODO maps are not cmp ed {:?} {:?}", a, b), a => a,
}
}
(Self::Map(_), _) => Less,
(_, Self::Map(_)) => Greater,
(
Self::Record(EdnRecordView {
tag: name1,
pairs: entries1,
}),
Self::Record(EdnRecordView {
tag: name2,
pairs: entries2,
}),
) => name1.cmp(name2).then_with(|| entries1.cmp(entries2)),
(Self::Record(..), _) => Less,
(_, Self::Record(..)) => Greater,
(Self::AnyRef(a), Self::AnyRef(b)) => {
if ptr::eq(a, b) {
Equal
} else {
unreachable!("anyref are not cmp ed {:?} {:?}", a, b)
}
}
}
}
}
impl PartialOrd for Edn {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Eq for Edn {}
impl PartialEq for Edn {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Nil, Self::Nil) => true,
(Self::Bool(a), Self::Bool(b)) => a == b,
(Self::Number(a), Self::Number(b)) => (a - b).abs() < f64::EPSILON,
(Self::Symbol(a), Self::Symbol(b)) => a == b,
(Self::Tag(a), Self::Tag(b)) => a == b,
(Self::Str(a), Self::Str(b)) => a == b,
(Self::Quote(a), Self::Quote(b)) => a == b,
(Self::Tuple(a), Self::Tuple(b)) => a == b,
(Self::List(a), Self::List(b)) => a == b,
(Self::Buffer(a), Self::Buffer(b)) => a == b,
(Self::Set(a), Self::Set(b)) => a == b,
(Self::Map(a), Self::Map(b)) => a == b,
(Self::Record(a), Self::Record(b)) => a == b,
(Self::AnyRef(a), Self::AnyRef(b)) => a == b,
(_, _) => false,
}
}
}
impl Edn {
pub fn str<T: Into<Arc<str>>>(s: T) -> Self {
Edn::Str(s.into())
}
pub fn tag<T: Into<Arc<str>>>(s: T) -> Self {
Edn::Tag(EdnTag::new(s.into()))
}
pub fn sym<T: Into<Arc<str>>>(s: T) -> Self {
Edn::Symbol(s.into())
}
pub fn tuple(tag: Self, extra: Vec<Self>) -> Self {
Edn::Tuple(EdnTupleView {
tag: Arc::new(tag),
extra,
})
}
pub fn any_ref<T: ToOwned + DynEq + 'static>(d: T) -> Self {
Edn::AnyRef(EdnAnyRef::new(d))
}
pub fn is_literal(&self) -> bool {
matches!(
self,
Self::Nil | Self::Bool(_) | Self::Number(_) | Self::Symbol(_) | Self::Tag(_) | Self::Str(_)
)
}
pub fn map_from_iter<T: IntoIterator<Item = (Edn, Edn)>>(pairs: T) -> Self {
Self::Map(EdnMapView(HashMap::from_iter(pairs)))
}
pub fn record_from_pairs(tag: EdnTag, pairs: &[(EdnTag, Edn)]) -> Self {
Self::Record(EdnRecordView {
tag,
pairs: pairs.to_vec(),
})
}
pub fn read_string(&self) -> Result<String, String> {
match self {
Edn::Str(s) => Ok((**s).to_owned()),
a => Err(format!("failed to convert to string: {}", a)),
}
}
pub fn read_symbol_string(&self) -> Result<String, String> {
match self {
Edn::Symbol(s) => Ok((**s).to_owned()),
a => Err(format!("failed to convert to symbol: {}", a)),
}
}
pub fn read_str(&self) -> Result<Arc<str>, String> {
match self {
Edn::Str(s) => Ok(s.to_owned()),
a => Err(format!("failed to convert to string: {}", a)),
}
}
pub fn read_symbol_str(&self) -> Result<Arc<str>, String> {
match self {
Edn::Symbol(s) => Ok(s.to_owned()),
a => Err(format!("failed to convert to symbol: {}", a)),
}
}
pub fn read_tag_str(&self) -> Result<Arc<str>, String> {
match self {
Edn::Tag(s) => Ok(s.arc_str()),
a => Err(format!("failed to convert to tag: {}", a)),
}
}
pub fn read_bool(&self) -> Result<bool, String> {
match self {
Edn::Bool(b) => Ok(*b),
a => Err(format!("failed to convert to bool: {}", a)),
}
}
pub fn read_number(&self) -> Result<f64, String> {
match self {
Edn::Number(n) => Ok(*n),
a => Err(format!("failed to convert to number: {}", a)),
}
}
pub fn read_quoted_cirru(&self) -> Result<Cirru, String> {
match self {
Edn::Quote(c) => Ok(c.to_owned()),
a => Err(format!("failed to convert to cirru code: {}", a)),
}
}
pub fn view_list(&self) -> Result<EdnListView, String> {
match self {
Edn::List(xs) => Ok((*xs).to_owned()),
Edn::Nil => Ok(EdnListView::default()),
a => Err(format!("failed to convert to list: {}", a)),
}
}
pub fn view_map(&self) -> Result<EdnMapView, String> {
match self {
Edn::Map(xs) => Ok(xs.to_owned()),
Edn::Nil => Ok(EdnMapView::default()),
a => Err(format!("failed to convert to map: {}", a)),
}
}
pub fn view_set(&self) -> Result<EdnSetView, String> {
match self {
Edn::Set(xs) => Ok(xs.to_owned()),
Edn::Nil => Ok(EdnSetView::default()),
a => Err(format!("failed to convert to set: {}", a)),
}
}
pub fn view_record(&self) -> Result<EdnRecordView, String> {
match self {
Edn::Record(EdnRecordView { tag, pairs }) => Ok(EdnRecordView {
tag: tag.to_owned(),
pairs: pairs.to_owned(),
}),
a => Err(format!("failed to convert to record: {}", a)),
}
}
pub fn view_tuple(&self) -> Result<EdnTupleView, String> {
match self {
Edn::Tuple(EdnTupleView { tag, extra }) => Ok(EdnTupleView {
tag: tag.to_owned(),
extra: extra.to_owned(),
}),
a => Err(format!("failed to convert to tuple: {}", a)),
}
}
}
impl TryFrom<Edn> for EdnTag {
type Error = String;
fn try_from(x: Edn) -> Result<EdnTag, String> {
match x {
Edn::Tag(k) => Ok(k),
_ => Err(format!("failed to convert to tag: {}", x)),
}
}
}
impl From<EdnTag> for Edn {
fn from(k: EdnTag) -> Edn {
Edn::Tag(k)
}
}
impl From<&EdnTag> for Edn {
fn from(k: &EdnTag) -> Edn {
Edn::Tag(k.to_owned())
}
}
impl TryFrom<Edn> for String {
type Error = String;
fn try_from(x: Edn) -> Result<String, Self::Error> {
match x {
Edn::Str(s) => Ok((*s).to_owned()),
Edn::Symbol(s) => Err(format!("cannot convert symbol {} into string", s)),
Edn::Tag(s) => Ok(s.to_string()),
a => Err(format!("failed to convert to string: {}", a)),
}
}
}
impl TryFrom<&Edn> for String {
type Error = String;
fn try_from(x: &Edn) -> Result<String, Self::Error> {
match x {
Edn::Str(s) => Ok((**s).to_owned()),
Edn::Symbol(s) => Err(format!("cannot convert symbol {} into string", s)),
Edn::Tag(s) => Ok(s.to_string()),
a => Err(format!("failed to convert to string: {}", a)),
}
}
}
impl From<String> for Edn {
fn from(x: String) -> Self {
Edn::Str(x.into())
}
}
impl From<&str> for Edn {
fn from(x: &str) -> Self {
Edn::Str(x.into())
}
}
impl From<Box<str>> for Edn {
fn from(x: Box<str>) -> Self {
Edn::Str(x.into())
}
}
impl From<&Box<str>> for Edn {
fn from(x: &Box<str>) -> Self {
Edn::Str((**x).into())
}
}
impl TryFrom<Edn> for Arc<str> {
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::Str(s) => Ok((*s).into()),
Edn::Tag(s) => Ok(s.arc_str()),
a => Err(format!("failed to convert to arc str: {}", a)),
}
}
}
impl From<Arc<str>> for Edn {
fn from(x: Arc<str>) -> Self {
Edn::Str((*x).into())
}
}
impl From<&Arc<str>> for Edn {
fn from(x: &Arc<str>) -> Self {
Edn::Str((**x).into())
}
}
impl TryFrom<Edn> for bool {
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::Bool(s) => Ok(s),
a => Err(format!("failed to convert to bool: {}", a)),
}
}
}
impl From<bool> for Edn {
fn from(x: bool) -> Self {
Edn::Bool(x)
}
}
impl From<&bool> for Edn {
fn from(x: &bool) -> Self {
Edn::Bool(*x)
}
}
impl TryFrom<Edn> for f64 {
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::Number(s) => Ok(s),
a => Err(format!("failed to convert to number: {}", a)),
}
}
}
impl From<f64> for Edn {
fn from(x: f64) -> Self {
Edn::Number(x)
}
}
impl From<&f64> for Edn {
fn from(x: &f64) -> Self {
Edn::Number(*x)
}
}
impl TryFrom<Edn> for f32 {
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::Number(s) => Ok(s as f32),
a => Err(format!("failed to convert to number: {}", a)),
}
}
}
impl From<f32> for Edn {
fn from(x: f32) -> Self {
Edn::Number(x as f64)
}
}
impl From<&f32> for Edn {
fn from(x: &f32) -> Self {
Edn::Number(*x as f64)
}
}
impl TryFrom<Edn> for i64 {
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::Number(s) => Ok(s as i64),
a => Err(format!("failed to convert to number: {}", a)),
}
}
}
impl From<i64> for Edn {
fn from(x: i64) -> Self {
Edn::Number(x as f64)
}
}
impl From<&i64> for Edn {
fn from(x: &i64) -> Self {
Edn::Number(*x as f64)
}
}
impl From<u8> for Edn {
fn from(x: u8) -> Self {
Edn::Number(x as f64)
}
}
impl From<&u8> for Edn {
fn from(x: &u8) -> Self {
Edn::Number(*x as f64)
}
}
impl From<usize> for Edn {
fn from(x: usize) -> Self {
Edn::Number(x as f64)
}
}
impl TryFrom<Edn> for u8 {
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::Number(s) => {
if s >= u8::MIN as f64 && s <= u8::MAX as f64 && s.fract().abs() <= f64::EPSILON {
Ok(s as u8)
} else {
Err(format!("invalid u8 value: {}", s))
}
}
a => Err(format!("failed to convert to u8: {}", a)),
}
}
}
impl From<i8> for Edn {
fn from(x: i8) -> Self {
Edn::Number(x as f64)
}
}
impl From<&i8> for Edn {
fn from(x: &i8) -> Self {
Edn::Number(*x as f64)
}
}
impl From<&[Edn]> for Edn {
fn from(xs: &[Edn]) -> Self {
Edn::List(EdnListView(xs.to_vec()))
}
}
impl TryFrom<Edn> for i8 {
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::Number(s) => {
if s >= i8::MIN as f64 && s <= i8::MAX as f64 && s.fract().abs() <= f64::EPSILON {
Ok(s as i8)
} else {
Err(format!("invalid i8 value: {}", s))
}
}
a => Err(format!("failed to convert to i8: {}", a)),
}
}
}
impl From<Cirru> for Edn {
fn from(x: Cirru) -> Self {
Edn::Quote(x)
}
}
impl From<&Cirru> for Edn {
fn from(x: &Cirru) -> Self {
Edn::Quote(x.to_owned())
}
}
impl TryFrom<Edn> for Cirru {
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::Quote(s) => Ok(s),
a => Err(format!("failed to convert to cirru code: {}", a)),
}
}
}
impl<T> TryFrom<Edn> for Vec<T>
where
T: TryFrom<Edn, Error = String>,
{
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::List(xs) => {
let mut ys = Vec::new();
for x in xs.0 {
let y = x.try_into()?;
ys.push(y);
}
Ok(ys)
}
Edn::Nil => Ok(vec![]),
a => Err(format!("failed to convert to vec: {}", a)),
}
}
}
impl<T> From<Option<T>> for Edn
where
T: Into<Edn>,
{
fn from(xs: Option<T>) -> Self {
match xs {
Some(x) => x.into(),
None => Edn::Nil,
}
}
}
impl<'a, T> From<&'a Option<&'a T>> for Edn
where
T: Into<Edn> + Clone,
{
fn from(xs: &'a Option<&'a T>) -> Self {
match xs {
Some(x) => (*x).to_owned().into(),
None => Edn::Nil,
}
}
}
impl<T> From<Vec<T>> for Edn
where
T: Into<Edn>,
{
fn from(xs: Vec<T>) -> Self {
Edn::List(EdnListView(xs.into_iter().map(|x| x.into()).collect()))
}
}
impl<'a, T> From<&'a Vec<&'a T>> for Edn
where
T: Into<Edn> + Clone,
{
fn from(xs: &'a Vec<&'a T>) -> Self {
Edn::List(EdnListView(xs.iter().map(|x| (*x).to_owned().into()).collect()))
}
}
impl<'a, T> From<&'a [&'a T]> for Edn
where
T: Into<Edn> + Clone,
{
fn from(xs: &'a [&'a T]) -> Self {
Edn::List(EdnListView(xs.iter().map(|x| (*x).to_owned().into()).collect()))
}
}
impl<T> TryFrom<Edn> for HashSet<T>
where
T: TryFrom<Edn, Error = String> + Eq + Hash,
{
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::Set(xs) => {
let mut ys = HashSet::new();
for x in xs.0 {
let y = x.try_into()?;
ys.insert(y);
}
Ok(ys)
}
Edn::Nil => Ok(HashSet::new()),
a => Err(format!("failed to convert to vec: {}", a)),
}
}
}
impl<T> From<HashSet<T>> for Edn
where
T: Into<Edn>,
{
fn from(xs: HashSet<T>) -> Self {
Edn::Set(EdnSetView(xs.into_iter().map(|x| x.into()).collect()))
}
}
impl<'a, T> From<&'a HashSet<&'a T>> for Edn
where
T: Into<Edn> + Clone,
{
fn from(xs: &'a HashSet<&'a T>) -> Self {
Edn::Set(EdnSetView(xs.iter().map(|x| (*x).to_owned().into()).collect()))
}
}
impl<T, K> TryFrom<Edn> for HashMap<K, T>
where
T: TryFrom<Edn, Error = String>,
K: TryFrom<Edn, Error = String> + Eq + Hash,
{
type Error = String;
fn try_from(x: Edn) -> Result<Self, Self::Error> {
match x {
Edn::Map(xs) => {
let mut ys = HashMap::new();
for (k, v) in &xs.0 {
let k = k.to_owned().try_into()?;
let v = v.to_owned().try_into()?;
ys.insert(k, v);
}
Ok(ys)
}
Edn::Nil => Ok(HashMap::new()),
a => Err(format!("failed to convert to vec: {}", a)),
}
}
}
impl<T, K> From<HashMap<K, T>> for Edn
where
T: Into<Edn>,
K: Into<Edn>,
{
fn from(xs: HashMap<K, T>) -> Self {
Edn::Map(EdnMapView(xs.into_iter().map(|(k, v)| (k.into(), v.into())).collect()))
}
}
impl<'a, T, K> From<&'a HashMap<&'a K, &'a T>> for Edn
where
T: Into<Edn> + Clone,
K: Into<Edn> + Clone,
{
fn from(xs: &'a HashMap<&'a K, &'a T>) -> Self {
Edn::Map(EdnMapView(
xs.iter()
.map(|(k, v)| ((*k).to_owned().into(), (*v).to_owned().into()))
.collect(),
))
}
}
impl From<(Arc<Edn>, Vec<Edn>)> for Edn {
fn from((tag, extra): (Arc<Edn>, Vec<Edn>)) -> Edn {
Edn::Tuple(EdnTupleView { tag, extra })
}
}