use crate::field_witnesses::{FieldName, HasField};
pub struct Path<F: FieldName, T: HasField<F>, Root> {
pub(crate) prefix: Vec<String>,
pub(crate) _marker: std::marker::PhantomData<(F, T, Root)>,
}
impl<F: FieldName, T: HasField<F>, Root> Path<F, T, Root> {
pub fn new() -> Self {
Self {
prefix: Vec::new(),
_marker: std::marker::PhantomData,
}
}
pub fn field<G: FieldName>(&self) -> Path<G, T::Value, Root>
where
T::Value: HasField<G>,
{
let mut prefix = self.prefix.clone();
prefix.push(F::field_name().to_string());
Path {
prefix,
_marker: std::marker::PhantomData,
}
}
}
impl<F: FieldName, T: HasField<F>, Root> Default for Path<F, T, Root> {
fn default() -> Self {
Self::new()
}
}
impl<F: FieldName, T: HasField<F>, Root> Clone for Path<F, T, Root> {
fn clone(&self) -> Self {
Self {
prefix: self.prefix.clone(),
_marker: std::marker::PhantomData,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestField;
impl FieldName for TestField {
fn field_name() -> &'static str {
"test_field"
}
}
struct NestedField;
impl FieldName for NestedField {
fn field_name() -> &'static str {
"nested_field"
}
}
struct DeepField;
impl FieldName for DeepField {
fn field_name() -> &'static str {
"deep_field"
}
}
struct DeepValue;
impl HasField<DeepField> for DeepValue {
type Value = String;
fn get_field(&self) -> &Self::Value {
unimplemented!("Test struct")
}
}
struct TestValue;
impl HasField<NestedField> for TestValue {
type Value = DeepValue;
fn get_field(&self) -> &Self::Value {
unimplemented!("Test struct")
}
}
struct TestStruct;
impl HasField<TestField> for TestStruct {
type Value = TestValue;
fn get_field(&self) -> &Self::Value {
unimplemented!("Test struct")
}
}
#[test]
fn test_path_new() {
let path = Path::<TestField, TestStruct, TestStruct>::new();
assert!(path.prefix.is_empty());
}
#[test]
fn test_path_default() {
let path: Path<TestField, TestStruct, TestStruct> = Default::default();
assert!(path.prefix.is_empty());
}
#[test]
fn test_path_clone() {
let mut path = Path::<TestField, TestStruct, TestStruct>::new();
path.prefix.push("existing".to_string());
let cloned = path.clone();
assert_eq!(path.prefix, cloned.prefix);
}
#[test]
fn test_path_field_navigation() {
let path = Path::<TestField, TestStruct, TestStruct>::new();
let nested_path = path.field::<NestedField>();
assert_eq!(nested_path.prefix, vec!["test_field"]);
}
#[test]
fn test_path_deep_navigation() {
let path = Path::<TestField, TestStruct, TestStruct>::new();
let nested_path = path.field::<NestedField>();
let deep_path: Path<DeepField, DeepValue, TestStruct> = nested_path.field::<DeepField>();
assert_eq!(deep_path.prefix, vec!["test_field", "nested_field"]);
}
}