Repository: typst/typst
File: crates/typst-ide/src/tests.rs (Rust)

Code before:
    fn font(&self, index: usize) -> Option<Font> {
        Some(self.base.fonts[index].clone())
    }

    fn today(&self, _: Option<i64>) -> Option<Datetime> {
        None
    }
}

impl IdeWorld for TestWorld {
    fn upcast(&self) -> &dyn World {
        self
    }

    fn files(&self) -> Vec<FileId> {
        std::iter::once(self.main.id())
            .chain(self.sources.keys().copied())
            .chain(self.assets.keys().copied())
            .collect()
    }

    fn packages(&self) -> &[(PackageSpec, Option<EcoString>)] {
        const LIST: &[(PackageSpec, Option<EcoString>)] = &[(
            PackageSpec {
                // NOTE: DEFAULT_NAMESPACE (i.e. "preview") in typst-kit/src/package.rs
                namespace: EcoString::inline("preview"),
                name: EcoString::inline("example"),
                version: PackageVersion { major: 0, minor: 1, patch: 0 },
            },
            None,
        )];
        LIST
    }
}

/// Extra methods for [`Source`].
pub trait SourceExt {
    /// Negative cursors index from the back.
    fn cursor(&self, cursor: isize) -> usize;
}

impl SourceExt for Source {
    fn cursor(&self, cursor: isize) -> usize {
        if cursor < 0 {
            self.len_bytes().checked_add_signed(cursor).unwrap()
        } else {
            cursor as usize
        }
    }
}


Review comment (suggestion):
Ideally we'd just use the constant here. Maybe it can be moved to `typst-utils` if it's shared by multiple Typst crates, but dunno (cc @laurmaedje)

Code after:
    fn font(&self, index: usize) -> Option<Font> {
        Some(self.base.fonts[index].clone())
    }

    fn today(&self, _: Option<i64>) -> Option<Datetime> {
        None
    }
}

impl IdeWorld for TestWorld {
    fn upcast(&self) -> &dyn World {
        self
    }

    fn files(&self) -> Vec<FileId> {
        std::iter::once(self.main.id())
            .chain(self.sources.keys().copied())
            .chain(self.assets.keys().copied())
            .collect()
    }

    fn packages(&self) -> &[(PackageSpec, Option<EcoString>)] {
        const LIST: &[(PackageSpec, Option<EcoString>)] = &[(
            PackageSpec {
                // NOTE: This literal, `"preview"`, should match the const, `DEFAULT_NAMESPACE`,
                // defined in `crates/typst-kit/src/package.rs`. However, we should always use the
                // literal here, not `DEFAULT_NAMESPACE`, so that this test fails if its value
                // changes in an unexpected way.
                namespace: EcoString::inline("preview"),
                name: EcoString::inline("example"),
                version: PackageVersion { major: 0, minor: 1, patch: 0 },
            },
            None,
        )];
        LIST
    }
}

/// Extra methods for [`Source`].
pub trait SourceExt {
    /// Negative cursors index from the back.
    fn cursor(&self, cursor: isize) -> usize;
}

impl SourceExt for Source {
    fn cursor(&self, cursor: isize) -> usize {
        if cursor < 0 {
            self.len_bytes().checked_add_signed(cursor).unwrap()
        } else {
            cursor as usize
        }