2023-10-27 01:23:39 +00:00
use serde ::Serialize ;
2023-08-22 15:40:50 +00:00
use std ::{
2023-10-26 20:00:06 +00:00
cmp ::Ordering ,
2023-08-22 15:40:50 +00:00
collections ::BTreeMap ,
fmt ::{ self , Display , Formatter } ,
2023-10-27 01:23:39 +00:00
sync ::{ Arc , RwLock } ,
2023-08-22 15:40:50 +00:00
} ;
2023-10-26 22:03:59 +00:00
use crate ::{ value ::Value , Error , List , Result , Table } ;
2023-08-22 15:40:50 +00:00
2023-08-24 04:26:37 +00:00
/// A collection dust variables comprised of key-value pairs.
///
/// The inner value is a BTreeMap in order to allow VariableMap instances to be sorted and compared
/// to one another.
2023-10-26 20:00:06 +00:00
#[ derive(Clone, Debug) ]
2023-10-25 20:44:50 +00:00
pub struct Map {
2023-10-26 20:00:06 +00:00
variables : Arc < RwLock < BTreeMap < String , Value > > > ,
2023-08-22 15:40:50 +00:00
}
2023-10-25 20:44:50 +00:00
impl Map {
2023-08-22 15:40:50 +00:00
/// Creates a new instace.
pub fn new ( ) -> Self {
2023-10-25 20:44:50 +00:00
Map {
2023-10-26 20:00:06 +00:00
variables : Arc ::new ( RwLock ::new ( BTreeMap ::new ( ) ) ) ,
2023-08-22 15:40:50 +00:00
}
}
2023-08-24 02:39:32 +00:00
/// Returns a Value assigned to the identifer, allowing dot notation to retrieve Values that are /// nested in Lists or Maps. Returns None if there is no variable with a key matching the /// identifier. Returns an error if a Map or List is indexed incorrectly.
2023-08-22 15:40:50 +00:00
pub fn get_value ( & self , identifier : & str ) -> Result < Option < Value > > {
2023-10-26 20:00:06 +00:00
let variables = self . variables . read ( ) . unwrap ( ) ;
2023-08-24 02:03:26 +00:00
let split = identifier . rsplit_once ( '.' ) ;
let ( found_value , next_identifier ) = if let Some ( ( identifier , next_identifier ) ) = split {
if identifier . contains ( '.' ) {
( self . get_value ( identifier ) ? , next_identifier )
2023-08-22 15:40:50 +00:00
} else {
2023-10-26 20:00:06 +00:00
( variables . get ( identifier ) . cloned ( ) , next_identifier )
2023-08-22 15:40:50 +00:00
}
} else {
2023-10-26 20:00:06 +00:00
return Ok ( variables . get ( identifier ) . cloned ( ) ) ;
2023-08-24 02:03:26 +00:00
} ;
2023-08-22 15:40:50 +00:00
2023-08-24 02:03:26 +00:00
if let Some ( value ) = found_value {
if let Value ::List ( list ) = value {
let index = if let Ok ( index ) = next_identifier . parse ::< usize > ( ) {
index
} else {
2023-10-13 16:26:44 +00:00
return Err ( Error ::ExpectedInt {
actual : Value ::String ( next_identifier . to_string ( ) ) ,
} ) ;
2023-08-24 02:03:26 +00:00
} ;
2023-10-26 22:03:59 +00:00
Ok ( list . items ( ) . get ( index ) . cloned ( ) )
2023-08-24 02:03:26 +00:00
} else if let Value ::Map ( map ) = value {
map . get_value ( next_identifier )
2023-08-22 15:40:50 +00:00
} else {
2023-08-24 02:03:26 +00:00
Ok ( Some ( value ) )
2023-08-22 15:40:50 +00:00
}
2023-08-24 02:03:26 +00:00
} else {
Ok ( None )
2023-08-22 15:40:50 +00:00
}
}
2023-08-24 02:39:32 +00:00
/// Assigns a variable with a Value and the identifier as its key, allowing dot notation to
/// assign nested lists and maps. Returns an error if a List or Map is indexed incorrectly.
2023-10-02 19:19:48 +00:00
pub fn set_value ( & mut self , key : String , value : Value ) -> Result < ( ) > {
let split = key . split_once ( '.' ) ;
2023-08-22 15:40:50 +00:00
2023-08-24 04:26:37 +00:00
if let Some ( ( identifier , next_identifier ) ) = split {
2023-10-26 20:00:06 +00:00
let mut variables = self . variables . write ( ) . unwrap ( ) ;
let get_value = variables . get_mut ( identifier ) ;
2023-08-22 15:40:50 +00:00
2023-08-24 03:07:54 +00:00
if let Some ( found_value ) = get_value {
if let Value ::List ( list ) = found_value {
let index = if let Ok ( index ) = next_identifier . parse ::< usize > ( ) {
index
} else {
2023-10-13 16:26:44 +00:00
return Err ( Error ::ExpectedInt {
actual : Value ::String ( next_identifier . to_string ( ) ) ,
} ) ;
2023-08-24 03:07:54 +00:00
} ;
2023-10-26 22:03:59 +00:00
let mut missing_elements = index . saturating_sub ( list . items ( ) . len ( ) ) + 1 ;
let mut items = list . items_mut ( ) ;
2023-08-24 03:07:54 +00:00
while missing_elements > 0 {
2023-10-26 22:03:59 +00:00
items . push ( value . clone ( ) ) ;
2023-08-24 03:07:54 +00:00
missing_elements - = 1 ;
}
Ok ( ( ) )
} else if let Value ::Map ( map ) = found_value {
2023-10-02 19:19:48 +00:00
map . set_value ( next_identifier . to_string ( ) , value )
2023-08-22 15:40:50 +00:00
} else {
Err ( Error ::ExpectedMap {
2023-08-24 03:07:54 +00:00
actual : found_value . clone ( ) ,
2023-08-22 15:40:50 +00:00
} )
}
} else {
2023-10-25 20:44:50 +00:00
let mut new_map = Map ::new ( ) ;
2023-08-22 15:40:50 +00:00
2023-10-02 19:19:48 +00:00
new_map . set_value ( next_identifier . to_string ( ) , value ) ? ;
2023-08-22 15:40:50 +00:00
self . variables
2023-10-26 20:00:06 +00:00
. write ( )
. unwrap ( )
2023-08-24 04:26:37 +00:00
. insert ( identifier . to_string ( ) , Value ::Map ( new_map ) ) ;
2023-08-22 15:40:50 +00:00
Ok ( ( ) )
}
} else {
2023-10-26 20:00:06 +00:00
self . variables
. write ( )
. unwrap ( )
. insert ( key . to_string ( ) , value ) ;
2023-08-22 15:40:50 +00:00
Ok ( ( ) )
}
}
2023-10-23 19:01:00 +00:00
/// Removes an assigned variable.
2023-10-07 01:00:31 +00:00
///
/// TODO: Support dot notation.
pub fn remove ( & mut self , key : & str ) -> Option < Value > {
2023-10-26 20:00:06 +00:00
self . variables . write ( ) . unwrap ( ) . remove ( key )
2023-10-07 01:00:31 +00:00
}
2023-08-22 15:40:50 +00:00
/// Returns a reference to the inner BTreeMap.
2023-10-26 20:00:06 +00:00
pub fn inner ( & self ) -> Arc < RwLock < BTreeMap < String , Value > > > {
Arc ::clone ( & self . variables )
2023-08-22 15:40:50 +00:00
}
/// Returns the number of stored variables.
pub fn len ( & self ) -> usize {
2023-10-26 20:00:06 +00:00
self . variables . read ( ) . unwrap ( ) . len ( )
2023-08-22 15:40:50 +00:00
}
/// Returns true if the length is zero.
pub fn is_empty ( & self ) -> bool {
2023-10-26 20:00:06 +00:00
self . variables . read ( ) . unwrap ( ) . is_empty ( )
2023-08-22 15:40:50 +00:00
}
}
2023-10-25 20:44:50 +00:00
impl Default for Map {
2023-08-22 15:40:50 +00:00
fn default ( ) -> Self {
Self ::new ( )
}
}
2023-10-26 20:00:06 +00:00
impl Eq for Map { }
impl PartialEq for Map {
fn eq ( & self , other : & Self ) -> bool {
let left = self . variables . read ( ) . unwrap ( ) . clone ( ) . into_iter ( ) ;
let right = other . variables . read ( ) . unwrap ( ) . clone ( ) . into_iter ( ) ;
left . eq ( right )
}
}
impl Ord for Map {
fn cmp ( & self , other : & Self ) -> Ordering {
let left = self . variables . read ( ) . unwrap ( ) . clone ( ) . into_iter ( ) ;
let right = other . variables . read ( ) . unwrap ( ) . clone ( ) . into_iter ( ) ;
left . cmp ( right )
}
}
impl PartialOrd for Map {
fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
let left = self . variables . read ( ) . unwrap ( ) . clone ( ) . into_iter ( ) ;
let right = other . variables . read ( ) . unwrap ( ) . clone ( ) . into_iter ( ) ;
left . partial_cmp ( right )
}
}
2023-10-25 20:44:50 +00:00
impl Display for Map {
2023-08-22 15:40:50 +00:00
fn fmt ( & self , f : & mut Formatter < '_ > ) -> fmt ::Result {
2023-10-14 18:18:13 +00:00
write! ( f , " {{ \n " ) ? ;
2023-10-26 20:00:06 +00:00
let variables = self . variables . read ( ) . unwrap ( ) . clone ( ) . into_iter ( ) ;
for ( key , value ) in variables {
2023-10-14 18:18:13 +00:00
write! ( f , " {key} = {value} \n " ) ? ;
}
write! ( f , " }} " )
2023-08-22 15:40:50 +00:00
}
}
2023-10-25 20:44:50 +00:00
impl From < & Table > for Map {
2023-08-22 15:40:50 +00:00
fn from ( value : & Table ) -> Self {
2023-10-25 20:44:50 +00:00
let mut map = Map ::new ( ) ;
2023-08-22 15:40:50 +00:00
for ( row_index , row ) in value . rows ( ) . iter ( ) . enumerate ( ) {
2023-10-26 22:03:59 +00:00
map . set_value (
row_index . to_string ( ) ,
Value ::List ( List ::with_items ( row . clone ( ) ) ) ,
)
. unwrap ( ) ;
2023-08-22 15:40:50 +00:00
}
map
}
}
2023-10-25 20:44:50 +00:00
impl Serialize for Map {
fn serialize < S > ( & self , serializer : S ) -> std ::result ::Result < S ::Ok , S ::Error >
where
S : serde ::Serializer ,
{
self . variables . serialize ( serializer )
}
}
2023-08-22 15:40:50 +00:00
#[ cfg(test) ]
mod tests {
use super ::* ;
#[ test ]
fn get_and_set_simple_value ( ) {
2023-10-25 20:44:50 +00:00
let mut map = Map ::new ( ) ;
2023-08-22 15:40:50 +00:00
2023-10-05 12:03:14 +00:00
map . set_value ( " x " . to_string ( ) , Value ::Integer ( 1 ) ) . unwrap ( ) ;
2023-08-22 15:40:50 +00:00
2023-10-05 12:03:14 +00:00
assert_eq! ( Value ::Integer ( 1 ) , map . get_value ( " x " ) . unwrap ( ) . unwrap ( ) ) ;
2023-08-22 15:40:50 +00:00
}
#[ test ]
fn get_and_set_nested_maps ( ) {
2023-10-25 20:44:50 +00:00
let mut map = Map ::new ( ) ;
2023-08-22 15:40:50 +00:00
2023-10-25 20:44:50 +00:00
map . set_value ( " x " . to_string ( ) , Value ::Map ( Map ::new ( ) ) )
2023-08-22 15:40:50 +00:00
. unwrap ( ) ;
2023-10-25 20:44:50 +00:00
map . set_value ( " x.x " . to_string ( ) , Value ::Map ( Map ::new ( ) ) )
2023-08-22 15:40:50 +00:00
. unwrap ( ) ;
2023-10-25 20:44:50 +00:00
map . set_value ( " x.x.x " . to_string ( ) , Value ::Map ( Map ::new ( ) ) )
2023-10-02 19:19:48 +00:00
. unwrap ( ) ;
2023-10-25 20:44:50 +00:00
map . set_value ( " x.x.x.x " . to_string ( ) , Value ::Map ( Map ::new ( ) ) )
2023-08-22 15:40:50 +00:00
. unwrap ( ) ;
assert_eq! (
2023-10-25 20:44:50 +00:00
Value ::Map ( Map ::new ( ) ) ,
2023-08-22 15:40:50 +00:00
map . get_value ( " x.x.x.x " ) . unwrap ( ) . unwrap ( )
) ;
}
}