use crate::adopter::*;
#[derive(Eq, PartialEq, Debug)]
pub struct ValuePtr<'tr, Value>
where Value: ValuePath + ValueReader
{
ptr: Option<&'tr Value>,
}
impl<'tr, Value> Copy for ValuePtr<'tr, Value>
where Value: ValuePath + ValueReader
{
}
impl<'tr, Value> Clone for ValuePtr<'tr, Value>
where Value: ValuePath + ValueReader
{
fn clone(&self) -> Self {
*self
}
}
#[derive(Eq, PartialEq, Debug)]
pub struct ValuePtrMut<'tr, Value>
where Value: ValuePath + ValueReader + ValueWriter
{
ptr: Option<&'tr mut Value>,
}
macro_rules! scalar_getter {
($func_name:ident | $ret:ty) => {
fn $func_name(&self, rhs: $ret) -> $ret {
match self.ptr {
Some(v) => v.$func_name(rhs),
None => rhs,
}
}
};
}
impl<'tr, Value> ValuePtr<'tr, Value>
where Value: ValuePath + ValueReader
{
pub fn new(ptr: Option<&'tr Value>) -> Self {
Self { ptr }
}
fn path_index(&self, i: usize) -> Self {
match self.ptr {
Some(v) => Self::new(v.get_index(i)),
None => Self::new(None)
}
}
fn path_str(&self, p: &str) -> Self {
if self.ptr.is_none() {
return Self::new(None);
}
let v = self.ptr.unwrap();
let target = v.get_key(p);
if target.is_some() {
Self::new(target)
}
else {
self.pathto(p)
}
}
pub fn pathto(&self, p: &str) -> Self {
if self.ptr.is_none() {
return Self::new(None);
}
let mut fixp = p;
if !p.is_empty() && p.chars().nth(0) == Some('/') {
fixp = &p[1..];
}
let target = fixp.split(&['/', '.'][..])
.map(|x| x.replace("~1", "/").replace("~0", "~"))
.try_fold(self.ptr.unwrap(), |value, token| {
value.get_key(&token).or_else(||
token.parse::<usize>().ok().and_then(|x| value.get_index(x))
)
});
Self::new(target)
}
fn get_str(&self, rhs: &'tr str) -> &'tr str {
match self.ptr {
Some(v) => v.get_str(rhs),
None => rhs,
}
}
scalar_getter!(get_string | String);
scalar_getter!(get_i64 | i64);
scalar_getter!(get_f64 | f64);
scalar_getter!(get_bool | bool);
}
impl<'tr, Value> ValuePtrMut<'tr, Value>
where Value: ValuePath + ValueReader + ValueWriter
{
pub fn new(ptr: Option<&'tr mut Value>) -> Self {
Self { ptr }
}
pub fn immut(&mut self) -> ValuePtr<'tr, Value> {
if self.ptr.is_none() {
return ValuePtr::new(None);
}
let v = self.ptr.take().unwrap();
ValuePtr::new(Some(v))
}
fn path_index(&mut self, i: usize) -> Self {
match self.ptr.take() {
Some(v) => Self::new(v.get_index_mut(i)),
None => Self::new(None)
}
}
fn path_str(&mut self, p: &str) -> Self {
if self.ptr.is_none() {
return Self::new(None);
}
let v = self.ptr.take().unwrap();
let target = v.get_key(p);
if target.is_some() {
Self::new(v.get_key_mut(p))
}
else {
self.ptr = Some(v); self.pathto(p)
}
}
pub fn pathto(&mut self, p: &str) -> Self {
if self.ptr.is_none() {
return Self::new(None);
}
let mut fixp = p;
if !p.is_empty() && p.chars().nth(0) == Some('/') {
fixp = &p[1..];
}
let target = fixp.split(&['/', '.'][..])
.map(|x| x.replace("~1", "/").replace("~0", "~"))
.try_fold(self.ptr.take().unwrap(), |value, token| {
let try_key = value.get_key(&token);
if try_key.is_some() {
value.get_key_mut(&token)
}
else {
token.parse::<usize>().ok().and_then(|x| value.get_index_mut(x))
}
});
Self::new(target)
}
fn put_value<T>(&mut self, rhs: T) -> Self where Value: From<T>, T: ScalarValue {
match self.ptr.take() {
Some(v) => { v.put_value(rhs); Self::new(Some(v)) },
None => Self::new(None)
}
}
fn push_object<K: ToString, T>(&mut self, key: K, val: T) -> Self where Value: From<T> {
match self.ptr.take() {
Some(v) => { v.push_object(key, val); Self::new(Some(v)) },
None => Self::new(None)
}
}
fn push_array<T>(&mut self, val: T) -> Self where Value: From<T> {
match self.ptr.take() {
Some(v) => { v.push_array(val); Self::new(Some(v)) },
None => Self::new(None)
}
}
}
include!("overload.rs");