Change series field type from :msg to :text

Update example to use :text for string fields in series. This aligns
with the new :text type support in the series implementation.
This commit is contained in:
Michael Schimmel
2026-03-05 15:07:31 +01:00
parent 6ebf31e2a0
commit 9ba4f795d1
2 changed files with 62 additions and 15 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
;; Benchmark: 1.0us ;; Benchmark: 1.0us
;; Benchmark-Repeat: 1944 ;; Benchmark-Repeat: 1944
(do (do
(def my_ticks (series {:price :float :volume :int :msg :string})) (def my_ticks (series {:price :float :volume :int :msg :text}))
(push my_ticks {:price 10.5 :volume 100 :msg "A"}) (push my_ticks {:price 10.5 :volume 100 :msg "A"})
(push my_ticks {:price 11.2 :volume 200 :msg "B"}) (push my_ticks {:price 11.2 :volume 200 :msg "B"})
+60 -13
View File
@@ -313,7 +313,12 @@ impl RecordSeries {
impl Debug for RecordSeries { impl Debug for RecordSeries {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "RecordSeries[fields: {}, len: {}]", self.fields.len(), Series::len(self)) write!(
f,
"RecordSeries[fields: {}, len: {}]",
self.fields.len(),
Series::len(self)
)
} }
} }
@@ -337,7 +342,10 @@ impl Series for RecordSeries {
self.fields.first().map(|f| f.borrow().len()).unwrap_or(0) self.fields.first().map(|f| f.borrow().len()).unwrap_or(0)
} }
fn total_count(&self) -> u64 { fn total_count(&self) -> u64 {
self.fields.first().map(|f| f.borrow().total_count()).unwrap_or(0) self.fields
.first()
.map(|f| f.borrow().total_count())
.unwrap_or(0)
} }
} }
@@ -359,7 +367,12 @@ impl SeriesView {
impl Debug for SeriesView { impl Debug for SeriesView {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SeriesView[field: {}, len: {}]", self.field_name.name(), Series::len(self)) write!(
f,
"SeriesView[field: {}, len: {}]",
self.field_name.name(),
Series::len(self)
)
} }
} }
@@ -428,8 +441,12 @@ impl<T: ScalarValue> Series for SharedSeries<T> {
.get(index) .get(index)
.map(|&v| (self.converter)(v)) .map(|&v| (self.converter)(v))
} }
fn len(&self) -> usize { self.buffer.borrow().len() } fn len(&self) -> usize {
fn total_count(&self) -> u64 { self.buffer.borrow().total_count() } self.buffer.borrow().len()
}
fn total_count(&self) -> u64 {
self.buffer.borrow().total_count()
}
} }
#[derive(Clone)] #[derive(Clone)]
@@ -459,8 +476,12 @@ impl Series for SharedValueSeries {
fn get_item(&self, index: usize) -> Option<Value> { fn get_item(&self, index: usize) -> Option<Value> {
self.buffer.borrow().get(index).cloned() self.buffer.borrow().get(index).cloned()
} }
fn len(&self) -> usize { self.buffer.borrow().len() } fn len(&self) -> usize {
fn total_count(&self) -> u64 { self.buffer.borrow().total_count() } self.buffer.borrow().len()
}
fn total_count(&self) -> u64 {
self.buffer.borrow().total_count()
}
} }
#[derive(Clone)] #[derive(Clone)]
@@ -509,10 +530,16 @@ impl Series for SharedRecordSeries {
Some(Value::Record(self.layout.clone(), Rc::new(vals))) Some(Value::Record(self.layout.clone(), Rc::new(vals)))
} }
fn len(&self) -> usize { fn len(&self) -> usize {
self.field_buffers.first().map(|f| f.borrow().len()).unwrap_or(0) self.field_buffers
.first()
.map(|f| f.borrow().len())
.unwrap_or(0)
} }
fn total_count(&self) -> u64 { fn total_count(&self) -> u64 {
self.field_buffers.first().map(|f| f.borrow().total_count()).unwrap_or(0) self.field_buffers
.first()
.map(|f| f.borrow().total_count())
.unwrap_or(0)
} }
} }
@@ -532,17 +559,37 @@ pub fn register(env: &Environment) {
|args: &[Value]| { |args: &[Value]| {
let arg = &args[0]; let arg = &args[0];
match arg { match arg {
Value::Record(layout, _) => Value::Object(Rc::new(RecordSeries::new(layout.clone()))),
Value::Keyword(k) => { Value::Keyword(k) => {
match k.name().to_lowercase().as_str() { match k.name().to_lowercase().as_str() {
"float" => Value::Object(Rc::new(ScalarSeries::<f64>::new("FloatSeries"))), "float" => Value::Object(Rc::new(ScalarSeries::<f64>::new("FloatSeries"))),
"int" | "datetime" => Value::Object(Rc::new(ScalarSeries::<i64>::new("IntSeries"))), "int" | "datetime" => Value::Object(Rc::new(ScalarSeries::<i64>::new("IntSeries"))),
"bool" => Value::Object(Rc::new(ScalarSeries::<bool>::new("BoolSeries"))), "bool" => Value::Object(Rc::new(ScalarSeries::<bool>::new("BoolSeries"))),
"any" => Value::Object(Rc::new(ValueSeries::new())), "text" => Value::Object(Rc::new(ValueSeries::new())),
_ => panic!("Unknown series type keyword: :{}", k.name()), _ => panic!("Unknown or unsupported series type keyword: :{}", k.name()),
} }
} }
_ => panic!("series expects a record template or a type keyword (e.g., :float, :int, :bool, :any)"), Value::Record(schema_layout, schema_values) => {
// Interpret the record as a schema: { :field :type_keyword }
let mut fields = Vec::with_capacity(schema_layout.fields.len());
for (i, (name, _)) in schema_layout.fields.iter().enumerate() {
let type_keyword = match &schema_values[i] {
Value::Keyword(tk) => tk.name().to_lowercase(),
_ => panic!("Field :{} in series schema must be a type keyword (e.g., :float, :int)", name.name()),
};
let ty = match type_keyword.as_str() {
"float" => StaticType::Float,
"int" => StaticType::Int,
"bool" => StaticType::Bool,
"datetime" => StaticType::DateTime,
"text" => StaticType::Text,
_ => panic!("Unsupported type keyword :{} for series field :{}", type_keyword, name.name()),
};
fields.push((*name, ty));
}
let final_layout = RecordLayout::get_or_create(fields);
Value::Object(Rc::new(RecordSeries::new(final_layout)))
}
_ => panic!("series expects a type keyword (:float, :int...) or a schema record (e.g., {{:price :float}})"),
} }
}, },
); );