From 5e4d94c579276b6adb8d1bb3aff9eb1840bafaf9 Mon Sep 17 00:00:00 2001 From: Cathal Mullan Date: Wed, 14 Jan 2026 21:55:52 +0000 Subject: [PATCH] feat: Add `no_std` support --- .github/workflows/ci.yml | 17 ++++++++++++++++- Cargo.toml | 7 ++++--- src/level.rs | 6 ++++-- src/lib.rs | 5 +++++ src/renderer/margin.rs | 2 +- src/renderer/mod.rs | 2 ++ src/renderer/render.rs | 14 ++++++++------ src/renderer/source_map.rs | 23 +++++++++++++---------- src/renderer/styled_buffer.rs | 7 ++++--- src/snippet.rs | 7 +++++-- 10 files changed, 62 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19415e40..e7d3c264 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: permissions: contents: none name: CI - needs: [test, msrv, lockfile, docs, rustfmt, clippy, minimal-versions] + needs: [test, msrv, no-std, lockfile, docs, rustfmt, clippy, minimal-versions] runs-on: ubuntu-latest if: "always()" steps: @@ -68,6 +68,21 @@ jobs: - uses: taiki-e/install-action@cargo-hack - name: Default features run: cargo hack check --each-feature --locked --rust-version --ignore-private --workspace --lib --bins --keep-going + no-std: + name: "Check no_std" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + targets: thumbv6m-none-eabi + - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack + - name: Build + run: cargo hack check --each-feature --skip default,std --locked --lib --target thumbv6m-none-eabi --keep-going minimal-versions: name: Minimal versions runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 9f33de91..c6837e35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,8 +124,8 @@ pre-release-replacements = [ maintenance = { status = "actively-developed" } [dependencies] -anstyle = "1.0.4" -memchr = { version = "2.7.4", optional = true } +anstyle = { version = "1.0.4", default-features = false } +memchr = { version = "2.7.4", default-features = false, optional = true } unicode-width = "0.2.2" [dev-dependencies] @@ -139,7 +139,8 @@ name = "bench" harness = false [features] -default = [] +default = ["std"] +std = ["anstyle/std", "memchr?/std"] simd = ["dep:memchr"] testing-colors = [] diff --git a/src/level.rs b/src/level.rs index ebc4a70d..230cf9e3 100644 --- a/src/level.rs +++ b/src/level.rs @@ -1,10 +1,12 @@ //! [`Level`] constants for easy importing +use alloc::borrow::Cow; + +use anstyle::Style; + use crate::renderer::stylesheet::Stylesheet; use crate::snippet::{ERROR_TXT, HELP_TXT, INFO_TXT, NOTE_TXT, WARNING_TXT}; use crate::{Message, OptionCow, Title}; -use anstyle::Style; -use std::borrow::Cow; /// Default `error:` [`Level`] pub const ERROR: Level<'_> = Level { diff --git a/src/lib.rs b/src/lib.rs index 5be58c8d..2900b77f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,11 +95,16 @@ //! cargo add annotate-snippets --dev --feature testing-colors //! ``` +#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(docsrs, feature(doc_cfg))] #![warn(clippy::print_stderr)] #![warn(clippy::print_stdout)] #![warn(missing_debug_implementations)] +extern crate alloc; + +use alloc::string::String; + pub mod level; pub mod renderer; mod snippet; diff --git a/src/renderer/margin.rs b/src/renderer/margin.rs index 4fb1e873..32503f99 100644 --- a/src/renderer/margin.rs +++ b/src/renderer/margin.rs @@ -1,4 +1,4 @@ -use std::cmp::{max, min}; +use core::cmp::{max, min}; const ELLIPSIS_PASSING: usize = 6; const LONG_WHITESPACE: usize = 20; diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index eaab6329..bd84c466 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -25,6 +25,8 @@ pub(crate) mod stylesheet; mod margin; mod styled_buffer; +use alloc::string::String; + use crate::Report; pub(crate) use render::normalize_whitespace; diff --git a/src/renderer/render.rs b/src/renderer/render.rs index 8cf7ffa2..3e726e90 100644 --- a/src/renderer/render.rs +++ b/src/renderer/render.rs @@ -1,9 +1,11 @@ // Most of this file is adapted from https://github.com/rust-lang/rust/blob/160905b6253f42967ed4aef4b98002944c7df24c/compiler/rustc_errors/src/emitter.rs -use std::borrow::Cow; -use std::cmp::{max, min, Ordering, Reverse}; -use std::collections::HashMap; -use std::fmt; +use alloc::borrow::{Cow, ToOwned}; +use alloc::collections::BTreeMap; +use alloc::string::{String, ToString}; +use alloc::{format, vec, vec::Vec}; +use core::cmp::{max, min, Ordering, Reverse}; +use core::fmt; use anstyle::Style; @@ -223,7 +225,7 @@ pub(crate) fn render(renderer: &Renderer, groups: Report<'_>) -> String { .render(&level, &renderer.stylesheet, &mut out_string) .unwrap(); if g != group_len - 1 { - use std::fmt::Write; + use core::fmt::Write; writeln!(out_string).unwrap(); } @@ -701,7 +703,7 @@ fn render_snippet_annotations( !is_cont && annotated_line_idx + 1 == annotated_lines.len(), ); - let mut to_add = HashMap::new(); + let mut to_add = BTreeMap::new(); for (depth, style) in depths { if let Some(index) = multilines.iter().position(|(d, _)| d == &depth) { diff --git a/src/renderer/source_map.rs b/src/renderer/source_map.rs index 88e2e2af..76170c27 100644 --- a/src/renderer/source_map.rs +++ b/src/renderer/source_map.rs @@ -1,8 +1,11 @@ +use alloc::borrow::Cow; +use alloc::string::String; +use alloc::{vec, vec::Vec}; +use core::cmp::{max, min}; +use core::ops::Range; + use crate::renderer::{char_width, num_overlap, LineAnnotation, LineAnnotationType}; use crate::{Annotation, AnnotationKind, Patch}; -use std::borrow::Cow; -use std::cmp::{max, min}; -use std::ops::Range; #[derive(Debug)] pub(crate) struct SourceMap<'a> { @@ -473,16 +476,16 @@ impl<'a> SourceMap<'a> { if prev_hi.line == cur_lo.line { let mut count = push_trailing(&mut buf, prev_line, &prev_hi, Some(&cur_lo)); while count > 0 { - highlights.push(std::mem::take(&mut line_highlight)); + highlights.push(core::mem::take(&mut line_highlight)); acc = 0; count -= 1; } } else { acc = 0; - highlights.push(std::mem::take(&mut line_highlight)); + highlights.push(core::mem::take(&mut line_highlight)); let mut count = push_trailing(&mut buf, prev_line, &prev_hi, None); while count > 0 { - highlights.push(std::mem::take(&mut line_highlight)); + highlights.push(core::mem::take(&mut line_highlight)); count -= 1; } // push lines between the previous and current span (if any) @@ -490,7 +493,7 @@ impl<'a> SourceMap<'a> { if let Some(line) = self.get_line(idx) { buf.push_str(line.as_ref()); buf.push('\n'); - highlights.push(std::mem::take(&mut line_highlight)); + highlights.push(core::mem::take(&mut line_highlight)); } } if let Some(cur_line) = self.get_line(cur_lo.line) { @@ -527,7 +530,7 @@ impl<'a> SourceMap<'a> { prev_line = self.get_line(prev_hi.line); for line in part.replacement.split('\n').skip(1) { acc = 0; - highlights.push(std::mem::take(&mut line_highlight)); + highlights.push(core::mem::take(&mut line_highlight)); let end: usize = line .chars() .map(|c| match c { @@ -538,7 +541,7 @@ impl<'a> SourceMap<'a> { line_highlight.push(SubstitutionHighlight { start: 0, end }); } } - highlights.push(std::mem::take(&mut line_highlight)); + highlights.push(core::mem::take(&mut line_highlight)); if fold { // if the replacement already ends with a newline, don't print the next line if !buf.ends_with('\n') { @@ -549,7 +552,7 @@ impl<'a> SourceMap<'a> { if let Some(snippet) = self.span_to_snippet(prev_hi.byte..source_len) { buf.push_str(snippet); for _ in snippet.matches('\n') { - highlights.push(std::mem::take(&mut line_highlight)); + highlights.push(core::mem::take(&mut line_highlight)); } } } diff --git a/src/renderer/styled_buffer.rs b/src/renderer/styled_buffer.rs index b64aef9c..3ee8dbea 100644 --- a/src/renderer/styled_buffer.rs +++ b/src/renderer/styled_buffer.rs @@ -2,13 +2,14 @@ //! //! [styled_buffer]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_errors/src/styled_buffer.rs +use alloc::string::String; +use alloc::{vec, vec::Vec}; +use core::fmt::{self, Write}; + use crate::renderer::stylesheet::Stylesheet; use crate::renderer::ElementStyle; use crate::Level; -use std::fmt; -use std::fmt::Write; - #[derive(Debug)] pub(crate) struct StyledBuffer { lines: Vec>, diff --git a/src/snippet.rs b/src/snippet.rs index 02dfccf7..5cefca0e 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -1,9 +1,12 @@ //! Structures used as an input for the library. +use alloc::borrow::{Cow, ToOwned}; +use alloc::string::String; +use alloc::{vec, vec::Vec}; +use core::ops::Range; + use crate::renderer::source_map::{as_substr, TrimmedPatch}; use crate::Level; -use std::borrow::Cow; -use std::ops::Range; pub(crate) const ERROR_TXT: &str = "error"; pub(crate) const HELP_TXT: &str = "help";