Skip to main content

diskann_benchmark_runner/
input.rs

1/*
2 * Copyright (c) Microsoft Corporation.
3 * Licensed under the MIT license.
4 */
5
6use crate::Checker;
7
8/// Inputs to [`Benchmarks`](crate::Benchmark).
9///
10/// These begin as [`raw`](Self::Raw) data transfer objects before final construction via
11/// [`from_raw`](Self::from_raw).
12pub trait Input: Sized + std::fmt::Debug + 'static {
13    /// The raw form of this input that is deserialized from input files and serialized as
14    /// [`examples`](Self::example). The raw nature of this type reflects that no input
15    /// validation has been performed beyond the checks performed by its
16    /// [`Deserialize`](serde::Deserialize) implementation.
17    ///
18    /// Final object validation is performed via [`from_raw`](Self::from_raw).
19    type Raw: serde::de::DeserializeOwned + serde::Serialize;
20
21    /// Return the discriminant associated with this type.
22    ///
23    /// This is used to map inputs types to their respective parsers.
24    ///
25    /// Well formed implementations should always return the same result.
26    fn tag() -> &'static str;
27
28    /// Construct `Self` from the raw deserialized representation, performing any necessary
29    /// validation checks (e.g., resolving file paths via the [`Checker`]).
30    fn from_raw(raw: Self::Raw, checker: &mut Checker) -> anyhow::Result<Self>;
31
32    /// Serialize `self` to a [`serde_json::Value`].
33    fn serialize(&self) -> anyhow::Result<serde_json::Value>;
34
35    /// Return an example of a raw input for this [`Input`].
36    ///
37    /// This is used to supply sample JSON layouts in the benchmark CLI.
38    fn example() -> Self::Raw;
39}
40
41/// A registered input. See [`crate::Registry::input`].
42#[derive(Clone, Copy)]
43pub struct Registered<'a>(pub(crate) &'a dyn internal::DynInput);
44
45impl Registered<'_> {
46    /// Return the input tag of the registered input.
47    ///
48    /// See: [`Input::tag`].
49    pub fn tag(&self) -> &'static str {
50        self.0.tag()
51    }
52
53    /// Try to deserialize raw JSON into the dynamic type of the input.
54    ///
55    /// See: [`Input::from_raw`].
56    pub(crate) fn try_deserialize(
57        &self,
58        serialized: &serde_json::Value,
59        checker: &mut Checker,
60    ) -> anyhow::Result<internal::Any> {
61        self.0.try_deserialize(serialized, checker)
62    }
63
64    /// Return an example JSON for the dynamic type of the input.
65    ///
66    /// See: [`Input::example`].
67    pub fn example(&self) -> anyhow::Result<serde_json::Value> {
68        self.0.example()
69    }
70}
71
72impl std::fmt::Debug for Registered<'_> {
73    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74        f.debug_struct("input::Registered")
75            .field("tag", &self.tag())
76            .finish()
77    }
78}
79
80pub(crate) mod internal {
81    use super::*;
82
83    /// Runtime representation of a deserialized [`Input`].
84    #[derive(Debug)]
85    pub(crate) struct Any {
86        any: Box<dyn RuntimeAny>,
87    }
88
89    impl Any {
90        pub(crate) fn new<T>(input: T) -> Self
91        where
92            T: Input,
93        {
94            Self {
95                any: Box::new(input),
96            }
97        }
98
99        #[must_use = "this function has no side effects"]
100        pub(crate) fn tag(&self) -> &'static str {
101            self.any.tag()
102        }
103
104        #[must_use = "this function has no side effects"]
105        pub(crate) fn downcast_ref<T>(&self) -> Option<&T>
106        where
107            T: std::any::Any,
108        {
109            self.any.as_any().downcast_ref::<T>()
110        }
111
112        #[must_use = "this function has no side effects"]
113        pub(crate) fn serialize(&self) -> anyhow::Result<serde_json::Value> {
114            self.any.serialize()
115        }
116    }
117
118    trait RuntimeAny: std::fmt::Debug {
119        fn tag(&self) -> &'static str;
120        fn as_any(&self) -> &dyn std::any::Any;
121        fn serialize(&self) -> anyhow::Result<serde_json::Value>;
122    }
123
124    impl<T> RuntimeAny for T
125    where
126        T: Input,
127    {
128        fn tag(&self) -> &'static str {
129            <Self as Input>::tag()
130        }
131
132        fn as_any(&self) -> &dyn std::any::Any {
133            self
134        }
135
136        fn serialize(&self) -> anyhow::Result<serde_json::Value> {
137            <Self as Input>::serialize(self)
138        }
139    }
140
141    #[derive(Debug)]
142    pub(crate) struct Wrapper<T>(std::marker::PhantomData<T>);
143
144    impl<T> Wrapper<T> {
145        pub(crate) const INSTANCE: Self = Self::new();
146
147        pub(crate) const fn new() -> Self {
148            Self(std::marker::PhantomData)
149        }
150    }
151
152    impl<T> Clone for Wrapper<T> {
153        fn clone(&self) -> Self {
154            *self
155        }
156    }
157
158    impl<T> Copy for Wrapper<T> {}
159
160    pub(crate) trait DynInput {
161        fn tag(&self) -> &'static str;
162        fn try_deserialize(
163            &self,
164            serialized: &serde_json::Value,
165            checker: &mut Checker,
166        ) -> anyhow::Result<Any>;
167        fn example(&self) -> anyhow::Result<serde_json::Value>;
168
169        // reflection
170        fn as_any(&self) -> &dyn std::any::Any;
171        fn type_name(&self) -> &'static str;
172    }
173
174    impl<T> DynInput for Wrapper<T>
175    where
176        T: Input,
177    {
178        fn tag(&self) -> &'static str {
179            T::tag()
180        }
181        fn try_deserialize(
182            &self,
183            serialized: &serde_json::Value,
184            checker: &mut Checker,
185        ) -> anyhow::Result<Any> {
186            let raw = <T::Raw as serde::Deserialize<'_>>::deserialize(serialized)?;
187            Ok(Any::new(T::from_raw(raw, checker)?))
188        }
189        fn example(&self) -> anyhow::Result<serde_json::Value> {
190            Ok(serde_json::to_value(T::example())?)
191        }
192        fn as_any(&self) -> &dyn std::any::Any {
193            self
194        }
195        fn type_name(&self) -> &'static str {
196            std::any::type_name::<T>()
197        }
198    }
199}