use std::collections::HashMap;
use std::sync::Arc;
use super::scoring::DEFAULT_SAFETY_CAP;
#[derive(Copy, Clone, Debug)]
pub struct PriorityConfig {
pub max_string_graphemes: usize,
pub array_max_items: usize,
pub prefer_tail_arrays: bool,
pub array_bias: ArrayBias,
pub array_sampler: ArraySamplerStrategy,
pub line_budget_only: bool,
pub safety_cap: usize,
}
impl PriorityConfig {
pub fn new(max_string_graphemes: usize, array_max_items: usize) -> Self {
Self {
max_string_graphemes,
array_max_items,
prefer_tail_arrays: false,
array_bias: ArrayBias::HeadMidTail,
array_sampler: ArraySamplerStrategy::Default,
line_budget_only: false,
safety_cap: DEFAULT_SAFETY_CAP,
}
}
#[allow(
clippy::too_many_arguments,
reason = "Priority tuning bundles several independent knobs"
)]
pub fn for_budget(
max_string_graphemes: usize,
per_file_budget: usize,
prefer_tail_arrays: bool,
array_sampler: ArraySamplerStrategy,
line_budget_only: bool,
) -> Self {
let array_max_items = if line_budget_only {
usize::MAX
} else {
(per_file_budget / 2).max(1)
};
Self {
max_string_graphemes,
array_max_items,
prefer_tail_arrays,
array_bias: ArrayBias::HeadMidTail,
array_sampler,
line_budget_only,
safety_cap: DEFAULT_SAFETY_CAP,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct NodeId(pub usize);
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum NodeKind {
Null,
Bool,
Number,
String,
Array,
Object,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum ObjectType {
Object,
Fileset,
JsonlRoot,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum ArrayBias {
Head,
HeadMidTail,
HeadTail,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum ArraySamplerStrategy {
Default,
Head,
Tail,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum RankedNode {
Array {
node_id: NodeId,
key_in_object: Option<String>,
},
Object {
node_id: NodeId,
key_in_object: Option<String>,
},
SplittableLeaf {
node_id: NodeId,
key_in_object: Option<String>,
value: String,
},
LeafPart {
node_id: NodeId,
key_in_object: Option<String>,
},
AtomicLeaf {
node_id: NodeId,
key_in_object: Option<String>,
token: String,
},
}
impl RankedNode {
pub fn node_id(&self) -> NodeId {
match self {
RankedNode::Array { node_id, .. }
| RankedNode::Object { node_id, .. }
| RankedNode::SplittableLeaf { node_id, .. }
| RankedNode::LeafPart { node_id, .. }
| RankedNode::AtomicLeaf { node_id, .. } => *node_id,
}
}
pub fn key_in_object(&self) -> Option<&str> {
match self {
RankedNode::Array { key_in_object, .. }
| RankedNode::Object { key_in_object, .. }
| RankedNode::SplittableLeaf { key_in_object, .. }
| RankedNode::LeafPart { key_in_object, .. }
| RankedNode::AtomicLeaf { key_in_object, .. } => {
key_in_object.as_deref()
}
}
}
pub fn display_kind(&self) -> NodeKind {
match self {
RankedNode::Array { .. } => NodeKind::Array,
RankedNode::Object { .. } => NodeKind::Object,
RankedNode::SplittableLeaf { .. }
| RankedNode::LeafPart { .. }
| RankedNode::AtomicLeaf { .. } => NodeKind::String,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct NodeMetrics {
pub array_len: Option<usize>,
pub object_len: Option<usize>,
pub string_len: Option<usize>,
pub string_truncated: bool,
}
#[derive(Clone, Debug)]
pub struct PriorityOrder {
pub metrics: Vec<NodeMetrics>,
pub nodes: Vec<RankedNode>,
pub scores: Vec<u128>,
pub parent: Vec<Option<NodeId>>, pub children: Vec<Vec<NodeId>>, pub index_in_parent_array: Vec<Option<usize>>,
pub by_priority: Vec<NodeId>, pub total_nodes: usize,
pub object_type: Vec<ObjectType>,
pub code_lines: HashMap<usize, Arc<Vec<String>>>,
pub fileset_render_slots: Option<Vec<FilesetRenderSlot>>,
pub safety_cap_hit: bool,
}
#[derive(Copy, Clone, Debug)]
pub struct FilesetRenderSlot {
pub id: NodeId,
pub suppressed: bool,
}
impl PriorityOrder {
pub fn fileset_render_slots(&self) -> Option<&[FilesetRenderSlot]> {
self.fileset_render_slots.as_deref()
}
}
pub const ROOT_PQ_ID: usize = 0;