lance_encoding/
version.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright The Lance Authors
3
4use std::str::FromStr;
5
6use lance_core::{Error, Result};
7use snafu::location;
8
9pub const LEGACY_FORMAT_VERSION: &str = "0.1";
10pub const V2_FORMAT_2_0: &str = "2.0";
11pub const V2_FORMAT_2_1: &str = "2.1";
12pub const V2_FORMAT_2_2: &str = "2.2";
13
14/// Lance file version
15#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Ord, PartialOrd)]
16pub enum LanceFileVersion {
17    // Note that Stable must come AFTER the stable version and Next must come AFTER the next version
18    // this way comparisons like x >= V2_0 will work the same if x is Stable or V2_0
19    /// The legacy (0.1) format
20    Legacy,
21    #[default]
22    V2_0,
23    /// The latest stable release
24    Stable,
25    V2_1,
26    /// The latest unstable release
27    Next,
28    V2_2,
29}
30
31impl LanceFileVersion {
32    /// Convert Stable or Next to the actual version
33    pub fn resolve(&self) -> Self {
34        match self {
35            Self::Stable => Self::V2_0,
36            Self::Next => Self::V2_1,
37            _ => *self,
38        }
39    }
40
41    pub fn try_from_major_minor(major: u32, minor: u32) -> Result<Self> {
42        match (major, minor) {
43            (0, 0) => Ok(Self::Legacy),
44            (0, 1) => Ok(Self::Legacy),
45            (0, 2) => Ok(Self::Legacy),
46            (0, 3) => Ok(Self::V2_0),
47            (2, 0) => Ok(Self::V2_0),
48            (2, 1) => Ok(Self::V2_1),
49            (2, 2) => Ok(Self::V2_2),
50            _ => Err(Error::InvalidInput {
51                source: format!("Unknown Lance storage version: {}.{}", major, minor).into(),
52                location: location!(),
53            }),
54        }
55    }
56
57    pub fn to_numbers(&self) -> (u32, u32) {
58        match self {
59            Self::Legacy => (0, 2),
60            Self::V2_0 => (2, 0),
61            Self::V2_1 => (2, 1),
62            Self::V2_2 => (2, 2),
63            Self::Stable => self.resolve().to_numbers(),
64            Self::Next => self.resolve().to_numbers(),
65        }
66    }
67}
68
69impl std::fmt::Display for LanceFileVersion {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        write!(
72            f,
73            "{}",
74            match self {
75                Self::Legacy => LEGACY_FORMAT_VERSION,
76                Self::V2_0 => V2_FORMAT_2_0,
77                Self::V2_1 => V2_FORMAT_2_1,
78                Self::V2_2 => V2_FORMAT_2_2,
79                Self::Stable => "stable",
80                Self::Next => "next",
81            }
82        )
83    }
84}
85
86impl FromStr for LanceFileVersion {
87    type Err = Error;
88
89    fn from_str(value: &str) -> Result<Self> {
90        match value.to_lowercase().as_str() {
91            LEGACY_FORMAT_VERSION => Ok(Self::Legacy),
92            V2_FORMAT_2_0 => Ok(Self::V2_0),
93            V2_FORMAT_2_1 => Ok(Self::V2_1),
94            V2_FORMAT_2_2 => Ok(Self::V2_2),
95            "stable" => Ok(Self::Stable),
96            "legacy" => Ok(Self::Legacy),
97            "next" => Ok(Self::Next),
98            // Version 0.3 is an alias of 2.0
99            "0.3" => Ok(Self::V2_0),
100            _ => Err(Error::InvalidInput {
101                source: format!("Unknown Lance storage version: {}", value).into(),
102                location: location!(),
103            }),
104        }
105    }
106}