Stabilize output order by replacing HashMap
with BTreeMap
This commit is contained in:
parent
e985456c29
commit
4e6b4471cd
8 changed files with 31 additions and 32 deletions
|
@ -28,9 +28,9 @@ Linked ./people:id/5 -> ./people/Darrel
|
|||
./people/:state:id/CA/0 user.name Wulfrum
|
||||
./people/:state:id/CA/2 user.name Sandeep
|
||||
+ ghee del -v ./people -w name=Sofia
|
||||
Removed ./people:id/1
|
||||
Removed ./people/Sofia
|
||||
Removed ./people/:state:id/WA/1
|
||||
Removed ./people/Sofia
|
||||
Removed ./people:id/1
|
||||
+ ghee del -v ./people:id 3
|
||||
Removed ./people:id/3
|
||||
Removed ./people/Janella
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
walk_records, xattr_values,
|
||||
};
|
||||
|
||||
use std::{collections::HashMap, fs::remove_file, path::PathBuf};
|
||||
use std::{collections::BTreeMap, fs::remove_file, path::PathBuf};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum DelErr {
|
||||
|
@ -28,13 +28,13 @@ pub enum DelErr {
|
|||
/// Delete all instantiations of a record across tables
|
||||
/// If `record` is not provided it will be loaded from `record_path`
|
||||
fn unlink_record(
|
||||
indices: &HashMap<Key, PathBuf>,
|
||||
indices: &BTreeMap<Key, PathBuf>,
|
||||
record_path: &PathBuf,
|
||||
record: Option<&HashMap<Xattr, Value>>,
|
||||
record: Option<&BTreeMap<Xattr, Value>>,
|
||||
verbose: bool,
|
||||
) -> Result<()> {
|
||||
// Owned copy of record xattr values if we are loading them
|
||||
let loaded_xattr_values: Option<HashMap<Xattr, Value>> = if let Some(_) = record {
|
||||
let loaded_xattr_values: Option<BTreeMap<Xattr, Value>> = if let Some(_) = record {
|
||||
None
|
||||
} else {
|
||||
Some(xattr_values(record_path)?)
|
||||
|
|
|
@ -6,12 +6,12 @@ use crate::{
|
|||
xattr_values,
|
||||
};
|
||||
|
||||
use std::{collections::HashMap, io::Write, path::PathBuf};
|
||||
use std::{collections::BTreeMap, io::Write, path::PathBuf};
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct FileXattrs<'a, 'b> {
|
||||
path: String,
|
||||
xattrs: HashMap<&'a Xattr, &'b Value>,
|
||||
xattrs: BTreeMap<&'a Xattr, &'b Value>,
|
||||
}
|
||||
|
||||
pub fn get(
|
||||
|
@ -44,8 +44,7 @@ pub fn get(
|
|||
fields.clone()
|
||||
};
|
||||
if *json {
|
||||
let mut xattrs: HashMap<&Xattr, &Value> =
|
||||
HashMap::with_capacity(projected_fields.len());
|
||||
let mut xattrs: BTreeMap<&Xattr, &Value> = BTreeMap::new();
|
||||
|
||||
for field in projected_fields.iter() {
|
||||
let value = &all_field_values[field];
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
collections::BTreeMap,
|
||||
fs::{create_dir_all, hard_link, File},
|
||||
io::{stdin, BufRead, BufReader, Read},
|
||||
path::PathBuf,
|
||||
|
@ -28,9 +28,9 @@ pub enum InsErr {
|
|||
}
|
||||
|
||||
/// Interpret a JSON object as parsed xattr values
|
||||
fn json_to_record(json: &serde_json::Value) -> Result<HashMap<Xattr, Value>> {
|
||||
fn json_to_record(json: &serde_json::Value) -> Result<BTreeMap<Xattr, Value>> {
|
||||
if let serde_json::Value::Object(o) = json {
|
||||
let mut record: HashMap<Xattr, Value> = HashMap::new();
|
||||
let mut record: BTreeMap<Xattr, Value> = BTreeMap::new();
|
||||
for (k, v) in o {
|
||||
let xattr = Xattr::from(k.as_str());
|
||||
let value = Value::try_from(v.clone())?;
|
||||
|
@ -43,7 +43,7 @@ fn json_to_record(json: &serde_json::Value) -> Result<HashMap<Xattr, Value>> {
|
|||
}
|
||||
}
|
||||
|
||||
fn write_record_as_xattrs(path: &PathBuf, record: &HashMap<Xattr, Value>) -> Result<()> {
|
||||
fn write_record_as_xattrs(path: &PathBuf, record: &BTreeMap<Xattr, Value>) -> Result<()> {
|
||||
for (k, v) in record {
|
||||
let bytes = v.as_bytes();
|
||||
|
||||
|
|
20
src/lib.rs
20
src/lib.rs
|
@ -9,7 +9,7 @@ pub mod paths;
|
|||
mod test_support;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
collections::BTreeMap,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
|
@ -98,13 +98,13 @@ pub fn xattr_values_from_path(
|
|||
key: &Key,
|
||||
base_path: &PathBuf,
|
||||
path: &PathBuf,
|
||||
) -> Result<HashMap<Xattr, Value>> {
|
||||
) -> Result<BTreeMap<Xattr, Value>> {
|
||||
let base_len = base_path.components().count();
|
||||
|
||||
// Get just the parts of `path` that go beyond `base_path`
|
||||
let parts = path.components().skip(base_len).map(|c| c.as_os_str());
|
||||
|
||||
let mut values: HashMap<Xattr, Value> = HashMap::new();
|
||||
let mut values: BTreeMap<Xattr, Value> = BTreeMap::new();
|
||||
for (i, part) in parts.enumerate() {
|
||||
let subkey = &key.subkeys[i];
|
||||
let value = Value::from(part.to_str().ok_or(GheeErr::PathValueNotUtf8)?);
|
||||
|
@ -115,13 +115,13 @@ pub fn xattr_values_from_path(
|
|||
}
|
||||
|
||||
pub struct RecordVisit<'a, 'b, 'c> {
|
||||
all_indices: &'a HashMap<Key, PathBuf>,
|
||||
all_indices: &'a BTreeMap<Key, PathBuf>,
|
||||
path: &'b PathBuf,
|
||||
xattr_values: &'c HashMap<Xattr, Value>,
|
||||
xattr_values: &'c BTreeMap<Xattr, Value>,
|
||||
}
|
||||
|
||||
/// Return all indices of the table whose path is given
|
||||
pub fn indices(path: &PathBuf) -> Result<HashMap<Key, PathBuf>> {
|
||||
pub fn indices(path: &PathBuf) -> Result<BTreeMap<Key, PathBuf>> {
|
||||
let info = get_index_info(path)?;
|
||||
|
||||
let main_key = get_key(path)?.ok_or(GheeErr::KeyNotFound(path.clone()))?;
|
||||
|
@ -135,7 +135,7 @@ pub fn indices(path: &PathBuf) -> Result<HashMap<Key, PathBuf>> {
|
|||
/// The idea is that this will maximally speed up traversal of records, but this may
|
||||
/// depend on the cardinality / distribution of the subkey values
|
||||
pub fn best_index<'a>(
|
||||
indices: &'a HashMap<Key, PathBuf>,
|
||||
indices: &'a BTreeMap<Key, PathBuf>,
|
||||
where_: &Vec<Predicate>,
|
||||
) -> (&'a Key, &'a PathBuf) {
|
||||
let predicate_xattrs: Vec<Xattr> = where_.iter().map(|pred| pred.xattr.clone()).collect();
|
||||
|
@ -158,7 +158,7 @@ pub fn best_index<'a>(
|
|||
|
||||
/// Efficiently walk all records in a table that meet the predicate constraints
|
||||
pub fn walk_records<F: Fn(RecordVisit) -> Result<()>>(
|
||||
indices: &HashMap<Key, PathBuf>,
|
||||
indices: &BTreeMap<Key, PathBuf>,
|
||||
where_: &Vec<Predicate>,
|
||||
visitor: F,
|
||||
) -> Result<()> {
|
||||
|
@ -254,10 +254,10 @@ pub fn xattr_value<P: AsRef<Path>>(path: P, xattr: &Xattr) -> Result<Value> {
|
|||
|
||||
/// Get all xattr values for the given path;
|
||||
/// like `xattr::list` and `xattr::get` but parsed into our format.
|
||||
pub fn xattr_values<P: AsRef<Path>>(path: P) -> Result<HashMap<Xattr, Value>> {
|
||||
pub fn xattr_values<P: AsRef<Path>>(path: P) -> Result<BTreeMap<Xattr, Value>> {
|
||||
let path = path.as_ref();
|
||||
let xattrs = list_xattrs(path);
|
||||
let mut values: HashMap<Xattr, Value> = HashMap::with_capacity(xattrs.len());
|
||||
let mut values: BTreeMap<Xattr, Value> = BTreeMap::new();
|
||||
|
||||
for xattr in xattrs.into_iter() {
|
||||
let value = xattr_value(path, &xattr)?;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::HashMap, path::PathBuf};
|
||||
use std::{collections::BTreeMap, path::PathBuf};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -7,13 +7,13 @@ use crate::parser::key::Key;
|
|||
#[derive(Serialize, Deserialize)]
|
||||
pub struct IndexInfo {
|
||||
/// The indexed key and location of related indices
|
||||
pub related_indices: HashMap<Key, PathBuf>,
|
||||
pub related_indices: BTreeMap<Key, PathBuf>,
|
||||
}
|
||||
|
||||
impl Default for IndexInfo {
|
||||
fn default() -> Self {
|
||||
IndexInfo {
|
||||
related_indices: HashMap::new(),
|
||||
related_indices: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
collections::BTreeMap,
|
||||
ops::{Index, IndexMut},
|
||||
path::PathBuf,
|
||||
slice::Iter,
|
||||
|
@ -25,7 +25,7 @@ pub enum KeyErr {
|
|||
RecordNotObject,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct Key {
|
||||
pub subkeys: Vec<Xattr>,
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ impl Key {
|
|||
Ok(values)
|
||||
}
|
||||
|
||||
pub fn value_for_record(&self, record: &HashMap<Xattr, Value>) -> Result<Vec<Value>> {
|
||||
pub fn value_for_record(&self, record: &BTreeMap<Xattr, Value>) -> Result<Vec<Value>> {
|
||||
let mut values: Vec<Value> = Vec::with_capacity(self.subkeys.len());
|
||||
|
||||
for subkey in self.subkeys.iter() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::HashMap, ffi::OsStr};
|
||||
use std::{collections::BTreeMap, ffi::OsStr};
|
||||
|
||||
use clap::{builder::TypedValueParser, Arg, Command};
|
||||
use nom::{
|
||||
|
@ -23,7 +23,7 @@ impl Predicate {
|
|||
pub fn new(xattr: Xattr, relation: Relation) -> Self {
|
||||
Self { xattr, relation }
|
||||
}
|
||||
pub fn satisfied(&self, values: &HashMap<Xattr, Value>) -> bool {
|
||||
pub fn satisfied(&self, values: &BTreeMap<Xattr, Value>) -> bool {
|
||||
values
|
||||
.get(&self.xattr)
|
||||
.map_or(false, |v| self.relation.satisfied_by(v.clone()))
|
||||
|
|
Loading…
Reference in a new issue