Skip to content

Commit

Permalink
support interpretation parameters as attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
emanueldima committed Mar 12, 2024
1 parent 09f2cc1 commit 3451638
Show file tree
Hide file tree
Showing 24 changed files with 835 additions and 1,051 deletions.
6 changes: 3 additions & 3 deletions doc/issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
- /*[name|parameters|return_type] ??
- set value on the command line: '/username = "newuser"'
- https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/rustfmt/src/lib.rs^http^rust does not work
- '**[filter]' must be work as '**/*[filter]' (filter to be applied only on leaves)
- support rust/ts write: `hial './src/tests/rust.rs^rust/*[:function_item].label = "modified_fn_name"'`
- add http interpretation params: method=HEAD, accept=""
- support zip, markdown
- support 'copy source destination'
- support ^json^tree^xml
- support diff ./file.json^json^tree ./file.xml^xml^tree
- '**[filter]' must be work as '**/*[filter]' (filter to be applied only on leaves)
- support rust/ts write: `hial './src/tests/rust.rs^rust/*[:function_item].label = "modified_fn_name"'`
- add http interpretation params: method=HEAD, accept=""
- functions
- should blobs/bytes be part of value? they are only useful by reinterpretation

Expand Down
129 changes: 129 additions & 0 deletions src/api/elevation_registry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use std::{sync::Arc, sync::RwLock};

use indexmap::IndexMap;

use crate::{api::*, guard_ok, guard_some, warning};

use linkme::distributed_slice;

pub type ElevateParams = IndexMap<&'static str, OwnValue>;
pub type ElevateFn =
fn(source: Xell, target_interpretation: &'static str, params: &ElevateParams) -> Res<Xell>;
type TargetMap = IndexMap<&'static str, ElevateFn>;
type ElevationRegistry = IndexMap<&'static str, Arc<TargetMap>>;

#[derive(Debug, Clone)]
pub struct ElevationConstructor {
pub source_interpretations: &'static [&'static str],
pub target_interpretations: &'static [&'static str],
pub constructor: ElevateFn,
}

#[distributed_slice]
pub static ELEVATION_CONSTRUCTORS: [ElevationConstructor];

static ELEVATION_REGISTRY: RwLock<Option<ElevationRegistry>> = RwLock::new(None);

pub(super) fn elevation_registry(
interpretation: &str,
) -> Res<Arc<IndexMap<&'static str, ElevateFn>>> {
fn read(interpretation: &str) -> Option<Res<Arc<IndexMap<&'static str, ElevateFn>>>> {
let maybe_map = guard_ok!(ELEVATION_REGISTRY.read(), err => {
return Some(Err(caused(HErrKind::Internal, "elevation registry read lock error", err)));
});
let reader = guard_some!(maybe_map.as_ref(), { return None });
// debug!("-- elevation map {:?} -> {:?}",
// interpretation,
// reader
// .get(interpretation)
// .map(|m| m.keys().collect::<Vec<_>>())
// );
reader.get(interpretation).map(|e| Ok(e.clone()))
}

if let Some(x) = read(interpretation) {
return x;
}
init_elevation_registry()?;
if let Some(x) = read(interpretation) {
return x;
}
nores()
}

fn init_elevation_registry() -> Res<()> {
let mut writer = guard_ok!(ELEVATION_REGISTRY.write(), err => {
return Err(caused(HErrKind::Internal, "elevation map read lock error", err));
});

// check first, it could have been initialized inbetween
if writer.is_some() {
return Ok(());
}

let mut source_map: IndexMap<&'static str, IndexMap<&'static str, ElevateFn>> = IndexMap::new();

for ec in ELEVATION_CONSTRUCTORS {
for source_interpretation in ec.source_interpretations {
let target_map = source_map.entry(source_interpretation).or_default();
for target_interpretation in ec.target_interpretations {
if target_map.contains_key(target_interpretation) {
warning!(
"elevation map: {} -> {} already exists",
source_interpretation,
target_interpretation
);
} else {
target_map.insert(target_interpretation, ec.constructor);
}
}
}
}

let mut final_source_map = IndexMap::new();
for (source, target_map) in source_map {
final_source_map.insert(source, Arc::new(target_map.clone()));
}
// for (k, v) in final_source_map.iter() {
// let v = v.keys().collect::<Vec<_>>();
// debug!("init elevation_registry {:?} -> {:?}", k, v);
// }
*writer = Some(final_source_map);
Ok(())
}

pub(crate) fn auto_interpretation(cell: &Xell) -> Option<&str> {
if cell.interpretation() == "fs" && cell.read().ty().ok()? == "file" {
if let Ok(reader) = cell.read().err() {
if let Ok(Value::Str(name)) = reader.label() {
if name.ends_with(".c") {
return Some("c");
} else if name.ends_with(".javascript") {
return Some("javascript");
} else if name.ends_with(".json") {
return Some("json");
} else if name.ends_with(".rs") {
return Some("rust");
} else if name.ends_with(".toml") {
return Some("toml");
} else if name.ends_with(".xml") {
return Some("xml");
} else if name.ends_with(".yaml") || name.ends_with(".yml") {
return Some("yaml");
}
}
}
}
if cell.interpretation() == "value" {
if let Ok(reader) = cell.read().err() {
if let Ok(Value::Str(s)) = reader.value() {
if s.starts_with("http://") || s.starts_with("https://") {
return Some("http");
} else if s.starts_with('.') || s.starts_with('/') {
return Some("fs");
}
}
}
}
None
}
Loading

0 comments on commit 3451638

Please sign in to comment.