starlane_resources/
property.rs

1use crate::{SkewerCase, Resource, ResourceIdentifier, ResourceSelector, ResourceStub, FieldSelection, ResourcePath};
2use std::str::FromStr;
3use crate::error::Error;
4use crate::data::{DataSet, BinSrc, Meta};
5use serde::{Serialize,Deserialize};
6use std::collections::HashMap;
7use crate::parse::{parse_resource_property_value_selector, parse_resource_value_selector};
8use crate::status::Status;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct ResourceValueSelector {
12    pub resource: ResourcePath,
13    pub property: ResourcePropertyValueSelector,
14}
15
16impl ResourceValueSelector {
17    pub fn new( resource: ResourcePath, property: ResourcePropertyValueSelector ) -> Self {
18        Self{
19            resource,
20            property
21        }
22    }
23}
24
25impl FromStr for ResourceValueSelector {
26    type Err = Error;
27
28    fn from_str(s: &str) -> Result<Self, Self::Err> {
29        let (leftover, selector ) = parse_resource_value_selector(s)?;
30
31        if !leftover.is_empty() {
32            return Err(format!("could not parse ResourceValueSelector: '{}' trailing portion '{}'", s, leftover).into() );
33        } else {
34            return Ok(selector?);
35        }
36    }
37}
38
39
40
41#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
42pub enum DataSetAspectSelector {
43    All,
44    Exact(String)
45}
46
47impl DataSetAspectSelector {
48    pub fn filter( &self, set: DataSet<BinSrc> ) -> ResourceValue {
49        match self {
50            DataSetAspectSelector::Exact(aspect) => {
51                let mut rtn = DataSet::new();
52                if set.contains_key(aspect) {
53                    rtn.insert( aspect.clone(), set.get(aspect).expect(format!("expected aspect: {}", aspect).as_str() ).clone());
54                }
55                ResourceValue::DataSet(rtn)
56            }
57            DataSetAspectSelector::All => {
58                ResourceValue::DataSet(set)
59            }
60        }
61    }
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
65pub enum ResourcePropertyValueSelector {
66    None,
67    State{ aspect: DataSetAspectSelector, field: FieldValueSelector },
68    Status
69}
70
71impl ResourcePropertyValueSelector {
72
73    pub fn state() -> Self {
74        Self::State {
75            aspect: DataSetAspectSelector::All,
76            field: FieldValueSelector::All
77        }
78    }
79
80    pub fn state_aspect(aspect: &str) -> Self {
81        Self::State {
82            aspect: DataSetAspectSelector::Exact(aspect.to_string()),
83            field: FieldValueSelector::All
84        }
85    }
86
87    pub fn state_aspect_field(aspect: &str, field: &str) -> Self {
88        Self::State {
89            aspect: DataSetAspectSelector::Exact(aspect.to_string()),
90            field: FieldValueSelector::Meta(MetaFieldValueSelector::Exact(field.to_string()))
91        }
92    }
93
94    pub fn filter( &self, resource: Resource ) -> ResourceValue {
95        match self {
96            ResourcePropertyValueSelector::State { aspect: selector, field } => {
97                field.filter( selector.filter(resource.state) )
98            }
99            ResourcePropertyValueSelector::None => {
100                ResourceValue::None
101            }
102            ResourcePropertyValueSelector::Status => {
103                ResourceValue::None
104            }
105        }
106    }
107}
108
109impl FromStr for ResourcePropertyValueSelector {
110    type Err = Error;
111
112    fn from_str(s: &str) -> Result<Self, Self::Err> {
113        let (leftover,selector) = parse_resource_property_value_selector(s)?;
114        if !leftover.is_empty() {
115            Err(format!("could not parse entire ResourcePropertyValueSelector: {} because of remaining string: {}", s, leftover ).into())
116        } else {
117            Ok(selector?)
118        }
119    }
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
123pub enum FieldValueSelector {
124    All,
125    Meta(MetaFieldValueSelector)
126}
127
128impl FieldValueSelector {
129    pub fn filter( &self, selection: ResourceValue ) -> ResourceValue {
130
131        match self {
132            Self::All => {
133                if let ResourceValue::Meta(meta)  = selection {
134                    ResourceValue::Meta(meta)
135                } else {
136                    selection
137                }
138            }
139            Self::Meta(selector) => {
140               if let ResourceValue::Meta(meta)  = selection {
141                   selector.filter(meta)
142               } else {
143                   ResourceValue::None
144               }
145            }
146        }
147    }
148
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
152pub enum MetaFieldValueSelector {
153    All,
154    Exact(String)
155}
156
157impl MetaFieldValueSelector {
158    pub fn filter( &self, meta: Meta ) -> ResourceValue {
159        match self {
160           MetaFieldValueSelector::Exact(field) => {
161                if meta.contains_key(field) {
162                   let value = meta.get(field).expect(format!("expecting field: {}",field).as_str() );
163                   ResourceValue::String(value.clone())
164                } else {
165                    ResourceValue::None
166                }
167            }
168            MetaFieldValueSelector::All => {
169                ResourceValue::Meta(meta)
170            }
171        }
172    }
173}
174
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub enum ResourceValue {
178    None,
179    DataSet(DataSet<BinSrc>),
180    BinSrc(BinSrc),
181    String(String),
182    Meta(Meta),
183    Resource(Resource),
184    Status(Status)
185}
186
187impl ToString for ResourceValue {
188    fn to_string(&self) -> String {
189        match self {
190            ResourceValue::None => {
191                "".to_string()
192            }
193            ResourceValue::DataSet(data) => {
194                let mut rtn = String::new();
195                for (k,v) in data {
196                    match v {
197                        BinSrc::Memory(bin) => {
198                            rtn.push_str( String::from_utf8(bin.to_vec()).unwrap_or("UTF ERROR!".to_string() ).as_str() )
199                        }
200                    }
201                }
202                rtn
203            }
204            ResourceValue::BinSrc(v) => {
205                match v {
206                    BinSrc::Memory(bin) => {
207                        String::from_utf8(bin.to_vec()).unwrap_or("UTF ERROR!".to_string() )
208                    }
209                }
210
211            }
212            ResourceValue::String(string) => {
213                string.clone()
214            }
215            ResourceValue::Meta(_) => {
216                "Meta printing not supported yet.".to_string()
217            }
218            ResourceValue::Resource(_) => {
219                "Resource string printing not supported yet.".to_string()
220            }
221            ResourceValue::Status(status) => {
222                status.to_string()
223            }
224        }
225    }
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize)]
229pub struct ResourceValues<R> {
230    pub resource: R,
231    pub values: HashMap<ResourcePropertyValueSelector,ResourceValue>
232}
233
234impl <R> ResourceValues <R> {
235
236  pub fn empty(resource: R ) -> Self {
237      Self {
238          resource,
239          values: HashMap::new()
240      }
241  }
242
243  pub fn new(resource: R, values: HashMap<ResourcePropertyValueSelector,ResourceValue>) -> Self {
244      Self {
245          resource,
246          values
247      }
248  }
249
250  pub fn with<T>(self, resource: T) -> ResourceValues<T> {
251      ResourceValues{
252          resource,
253          values: self.values
254       }
255  }
256}
257
258