LCOV - code coverage report
Current view: top level - dashql-core-shell/src - lib.rs Coverage Total Hit
Test: DashQL 6e74948 Lines: 87.5 % 16 14
Test Date: 2026-11-06 17:46:50

            Line data    Source code
       1              : //! The DashQL shell: a readline-like prompt with SQL highlighting and completion, a VT100
       2              : //! terminal renderer, and the execution protocol of queries and dot commands.
       3              : //!
       4              : //! Queries and commands are pending effects: starting an operation returns
       5              : //! [`ShellStatus::Pending`] with an effect envelope (version, type, id, payload), and the host
       6              : //! completes or cancels the effect by id, which yields the rendered output.
       7              : //!
       8              : //! The session does not own its catalog. Operations that read it take `&Catalog`, operations that
       9              : //! may publish session relations take `&mut Catalog` (see [`ShellSession`]).
      10              : //!
      11              : //! Inputs that must be valid UTF-8 are byte slices so that invalid input is reported as an error,
      12              : //! and outputs are terminal bytes.
      13              : 
      14              : pub mod arrow_renderer;
      15              : pub mod prompt_buffer;
      16              : mod session;
      17              : pub mod session_relations;
      18              : pub mod unicode;
      19              : pub mod vt100;
      20              : 
      21              : pub use arrow_renderer::ArrowRenderer;
      22              : pub use prompt_buffer::PromptBuffer;
      23              : pub use session::ShellSession;
      24              : 
      25              : /// The status of a shell operation
      26              : #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
      27              : #[repr(u32)]
      28              : pub enum ShellStatus {
      29              :     Ok = 0,
      30              :     InvalidArgument = 1,
      31              :     ArrowError = 2,
      32              :     InternalError = 3,
      33              :     Pending = 4,
      34              :     StaleEffect = 5,
      35              :     Busy = 6,
      36              : }
      37              : 
      38              : /// The type of an effect
      39              : #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
      40              : #[repr(u32)]
      41              : pub enum EffectType {
      42              :     ExecuteQuery = 1,
      43              :     ExecuteCommand = 2,
      44              : }
      45              : 
      46              : /// How the host finished an effect
      47              : #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
      48              : #[repr(u32)]
      49              : pub enum EffectCompletionStatus {
      50              :     Success = 0,
      51              :     Error = 1,
      52              :     Cancelled = 2,
      53              : }
      54              : 
      55              : impl EffectCompletionStatus {
      56            2 :     pub fn from_u32(value: u32) -> Option<Self> {
      57            2 :         Some(match value {
      58            0 :             0 => Self::Success,
      59            0 :             1 => Self::Error,
      60            1 :             2 => Self::Cancelled,
      61            1 :             _ => return None,
      62              :         })
      63            2 :     }
      64              : }
      65              : 
      66              : /// A semantic input key
      67              : #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
      68              : #[repr(u32)]
      69              : pub enum PromptInputKey {
      70              :     Text = 0,
      71              :     Enter = 1,
      72              :     ForceSubmit = 2,
      73              :     Tab = 3,
      74              :     Backspace = 4,
      75              :     Delete = 5,
      76              :     Left = 6,
      77              :     Right = 7,
      78              :     HistoryPrevious = 8,
      79              :     HistoryNext = 9,
      80              :     Cancel = 10,
      81              :     Escape = 11,
      82              :     Up = 12,
      83              :     Down = 13,
      84              :     Start = 14,
      85              :     End = 15,
      86              :     LineStart = 16,
      87              :     LineEnd = 17,
      88              :     WordLeft = 18,
      89              :     WordRight = 19,
      90              :     KillLine = 20,
      91              :     BackwardKillLine = 21,
      92              :     KillWord = 22,
      93              :     BackwardKillWord = 23,
      94              :     Yank = 24,
      95              :     Transpose = 25,
      96              :     ClearScreen = 26,
      97              :     Eof = 27,
      98              :     Abort = 28,
      99              : }
     100              : 
     101              : impl PromptInputKey {
     102              :     pub const ALL: [PromptInputKey; 29] = [
     103              :         Self::Text,
     104              :         Self::Enter,
     105              :         Self::ForceSubmit,
     106              :         Self::Tab,
     107              :         Self::Backspace,
     108              :         Self::Delete,
     109              :         Self::Left,
     110              :         Self::Right,
     111              :         Self::HistoryPrevious,
     112              :         Self::HistoryNext,
     113              :         Self::Cancel,
     114              :         Self::Escape,
     115              :         Self::Up,
     116              :         Self::Down,
     117              :         Self::Start,
     118              :         Self::End,
     119              :         Self::LineStart,
     120              :         Self::LineEnd,
     121              :         Self::WordLeft,
     122              :         Self::WordRight,
     123              :         Self::KillLine,
     124              :         Self::BackwardKillLine,
     125              :         Self::KillWord,
     126              :         Self::BackwardKillWord,
     127              :         Self::Yank,
     128              :         Self::Transpose,
     129              :         Self::ClearScreen,
     130              :         Self::Eof,
     131              :         Self::Abort,
     132              :     ];
     133              : 
     134              :     /// The key of a numeric value, None for values past `ABORT`
     135            2 :     pub fn from_u32(value: u32) -> Option<Self> {
     136            2 :         Self::ALL.get(value as usize).copied()
     137            2 :     }
     138              : }
     139              : 
     140              : /// What the host should do after an input
     141              : #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
     142              : #[repr(u32)]
     143              : pub enum PromptInputAction {
     144              :     #[default]
     145              :     None = 0,
     146              :     Submit = 1,
     147              :     Complete = 2,
     148              :     Exit = 3,
     149              : }
     150              : 
     151              : /// The result of an operation: rendered output, an effect envelope or an error message
     152              : #[derive(Clone, Debug, PartialEq, Eq)]
     153              : pub struct ShellOperation {
     154              :     /// The status of the operation
     155              :     pub status: ShellStatus,
     156              :     /// The rendered output, the encoded effect envelope or the error message
     157              :     pub data: Vec<u8>,
     158              : }
     159              : 
     160              : impl ShellOperation {
     161          441 :     pub fn new(status: ShellStatus, data: impl Into<Vec<u8>>) -> Self {
     162          441 :         Self { status, data: data.into() }
     163          441 :     }
     164              : 
     165          371 :     pub fn ok(data: impl Into<Vec<u8>>) -> Self {
     166          371 :         Self::new(ShellStatus::Ok, data)
     167          371 :     }
     168              : }
     169              : 
     170              : /// Terminal output with the action of the input
     171              : #[derive(Clone, Debug, PartialEq, Eq)]
     172              : pub struct TerminalOutput {
     173              :     /// The status of the input
     174              :     pub status: ShellStatus,
     175              :     /// What the host should do after the input
     176              :     pub action: PromptInputAction,
     177              :     /// The terminal output with VT100 escape sequences, or the error message
     178              :     pub data: Vec<u8>,
     179              : }
     180              : 
     181              : /// A completion candidate of the prompt
     182              : #[derive(Clone, Debug, Default, PartialEq, Eq)]
     183              : pub struct CompletionCandidate {
     184              :     /// The text shown in the completion list
     185              :     pub display_text: String,
     186              :     /// The text that replaces the target, quoted if needed and with `()` for functions
     187              :     pub completion_text: String,
     188              :     /// The keywords that usually follow the completion, shown as hint, empty if none
     189              :     pub continuation_text: String,
     190              :     /// Whether this candidate only preserves the token already under the cursor
     191              :     pub is_identity: bool,
     192              :     /// The qualified names of the candidate objects that are shown as variants
     193              :     pub qualification_texts: Vec<String>,
     194              :     /// The cursor offset within the completion text after applying it
     195              :     pub completion_cursor_offset: u32,
     196              :     /// The byte offset of the replaced text in the prompt
     197              :     pub target_offset: u32,
     198              :     /// The byte length of the replaced text in the prompt
     199              :     pub target_length: u32,
     200              :     /// The byte offset of the text that a qualified name replaces
     201              :     pub qualification_target_offset: u32,
     202              :     /// The byte length of the text that a qualified name replaces
     203              :     pub qualification_target_length: u32,
     204              : }
     205              : 
     206              : /// The state of the prompt after an edit
     207              : #[derive(Clone, Debug, PartialEq, Eq)]
     208              : pub struct PromptSnapshot {
     209              :     /// The status of the edit
     210              :     pub status: ShellStatus,
     211              :     /// The revision of the prompt text
     212              :     pub revision: u64,
     213              :     /// The byte offset of the cursor in the text
     214              :     pub cursor_byte_offset: u32,
     215              :     /// The prompt text
     216              :     pub text: String,
     217              :     /// The error message, empty on success
     218              :     pub message: String,
     219              :     /// What the host should do after the edit
     220              :     pub action: PromptInputAction,
     221              : }
     222              : 
     223              : /// The version of the effect envelope
     224              : pub const EFFECT_ENVELOPE_VERSION: u32 = 1;
     225              : /// The size of the effect envelope header: version (u32), type (u32), id (u64), all little-endian
     226              : pub const EFFECT_ENVELOPE_HEADER_SIZE: usize = 16;
        

Generated by: LCOV version 2.0-1