diff --git a/libgrust/libformat_parser/generic_format_parser/src/lib.rs b/libgrust/libformat_parser/generic_format_parser/src/lib.rs index f42c9d8dffb..87a20dc18c5 100644 --- a/libgrust/libformat_parser/generic_format_parser/src/lib.rs +++ b/libgrust/libformat_parser/generic_format_parser/src/lib.rs @@ -1099,4 +1099,4 @@ fn unescape_string(string: &str) -> Option { // rustc_index::static_assert_size!(Piece<'_>, 16); // #[cfg(test)] -// mod tests; \ No newline at end of file +// mod tests; diff --git a/libgrust/libformat_parser/src/lib.rs b/libgrust/libformat_parser/src/lib.rs index e6dc16eeb49..49821e7cd2f 100644 --- a/libgrust/libformat_parser/src/lib.rs +++ b/libgrust/libformat_parser/src/lib.rs @@ -5,8 +5,298 @@ use std::ffi::CStr; -// TODO: Use rustc's version here #3 -use generic_format_parser::Piece; +mod ffi { + use std::ops::Deref; + + // Note: copied from rustc_span + /// Range inside of a `Span` used for diagnostics when we only have access to relative positions. + #[derive(Copy, Clone, PartialEq, Eq, Debug)] + #[repr(C)] + pub struct InnerSpan { + pub start: usize, + pub end: usize, + } + + // impl InnerSpan { + // pub fn new(start: usize, end: usize) -> InnerSpan { + // InnerSpan { start, end } + // } + // } + + /// The location and before/after width of a character whose width has changed from its source code + /// representation + #[derive(Copy, Clone, PartialEq, Eq)] + #[repr(C)] + pub struct InnerWidthMapping { + /// Index of the character in the source + pub position: usize, + /// The inner width in characters + pub before: usize, + /// The transformed width in characters + pub after: usize, + } + + // impl InnerWidthMapping { + // pub fn new(position: usize, before: usize, after: usize) -> InnerWidthMapping { + // InnerWidthMapping { + // position, + // before, + // after, + // } + // } + // } + + /// Whether the input string is a literal. If yes, it contains the inner width mappings. + #[derive(Clone, PartialEq, Eq)] + #[repr(C)] + enum InputStringKind { + NotALiteral, + Literal { + width_mappings: Vec, + }, + } + + /// The type of format string that we are parsing. + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + #[repr(C)] + pub enum ParseMode { + /// A normal format string as per `format_args!`. + Format, + /// An inline assembly template string for `asm!`. + InlineAsm, + } + + #[derive(Copy, Clone)] + #[repr(C)] + struct InnerOffset(usize); + + /// A piece is a portion of the format string which represents the next part + /// to emit. These are emitted as a stream by the `Parser` class. + #[derive(Clone, Debug, PartialEq)] + #[repr(C)] + pub enum Piece<'a> { + /// A literal string which should directly be emitted + String(&'a str), + /// This describes that formatting should process the next argument (as + /// specified inside) for emission. + NextArgument(Box>), + } + + /// Representation of an argument specification. + #[derive(Copy, Clone, Debug, PartialEq)] + #[repr(C)] + pub struct Argument<'a> { + /// Where to find this argument + pub position: Position<'a>, + /// The span of the position indicator. Includes any whitespace in implicit + /// positions (`{ }`). + pub position_span: InnerSpan, + /// How to format the argument + pub format: FormatSpec<'a>, + } + + /// Specification for the formatting of an argument in the format string. + #[derive(Copy, Clone, Debug, PartialEq)] + #[repr(C)] + pub struct FormatSpec<'a> { + /// Optionally specified character to fill alignment with. + pub fill: Option, + /// Span of the optionally specified fill character. + pub fill_span: Option, + /// Optionally specified alignment. + pub align: Alignment, + /// The `+` or `-` flag. + pub sign: Option, + /// The `#` flag. + pub alternate: bool, + /// The `0` flag. + pub zero_pad: bool, + /// The `x` or `X` flag. (Only for `Debug`.) + pub debug_hex: Option, + /// The integer precision to use. + pub precision: Count<'a>, + /// The span of the precision formatting flag (for diagnostics). + pub precision_span: Option, + /// The string width requested for the resulting format. + pub width: Count<'a>, + /// The span of the width formatting flag (for diagnostics). + pub width_span: Option, + /// The descriptor string representing the name of the format desired for + /// this argument, this can be empty or any number of characters, although + /// it is required to be one word. + pub ty: &'a str, + /// The span of the descriptor string (for diagnostics). + pub ty_span: Option, + } + + /// Enum describing where an argument for a format can be located. + #[derive(Copy, Clone, Debug, PartialEq)] + #[repr(C)] + pub enum Position<'a> { + /// The argument is implied to be located at an index + ArgumentImplicitlyIs(usize), + /// The argument is located at a specific index given in the format, + ArgumentIs(usize), + /// The argument has a name. + ArgumentNamed(&'a str), + } + + /// Enum of alignments which are supported. + #[derive(Copy, Clone, Debug, PartialEq)] + #[repr(C)] + pub enum Alignment { + /// The value will be aligned to the left. + AlignLeft, + /// The value will be aligned to the right. + AlignRight, + /// The value will be aligned in the center. + AlignCenter, + /// The value will take on a default alignment. + AlignUnknown, + } + + /// Enum for the sign flags. + #[derive(Copy, Clone, Debug, PartialEq)] + #[repr(C)] + pub enum Sign { + /// The `+` flag. + Plus, + /// The `-` flag. + Minus, + } + + /// Enum for the debug hex flags. + #[derive(Copy, Clone, Debug, PartialEq)] + #[repr(C)] + pub enum DebugHex { + /// The `x` flag in `{:x?}`. + Lower, + /// The `X` flag in `{:X?}`. + Upper, + } + + /// A count is used for the precision and width parameters of an integer, and + /// can reference either an argument or a literal integer. + #[derive(Copy, Clone, Debug, PartialEq)] + #[repr(C)] + pub enum Count<'a> { + /// The count is specified explicitly. + CountIs(usize), + /// The count is specified by the argument with the given name. + CountIsName(&'a str, InnerSpan), + /// The count is specified by the argument at the given index. + CountIsParam(usize), + /// The count is specified by a star (like in `{:.*}`) that refers to the argument at the given index. + CountIsStar(usize), + /// The count is implied and cannot be explicitly specified. + CountImplied, + } + + impl<'a> From> for Piece<'a> { + fn from(old: generic_format_parser::Piece<'a>) -> Self { + match old { + generic_format_parser::Piece::String(x) => Piece::String(x), + generic_format_parser::Piece::NextArgument(x) => { + Piece::NextArgument(Box::new(Into::::into(*x))) + } + } + } + } + + impl<'a> From> for Argument<'a> { + fn from(old: generic_format_parser::Argument<'a>) -> Self { + Argument { + position: old.position.into(), + position_span: old.position_span.into(), + format: old.format.into(), + } + } + } + + impl<'a> From> for Position<'a> { + fn from(old: generic_format_parser::Position<'a>) -> Self { + match old { + generic_format_parser::Position::ArgumentImplicitlyIs(x) => { + Position::ArgumentImplicitlyIs(x.into()) + } + generic_format_parser::Position::ArgumentIs(x) => Position::ArgumentIs(x.into()), + generic_format_parser::Position::ArgumentNamed(x) => { + Position::ArgumentNamed(x.into()) + } + } + } + } + + impl From for InnerSpan { + fn from(old: generic_format_parser::InnerSpan) -> Self { + InnerSpan { + start: old.start, + end: old.end, + } + } + } + + impl<'a> From> for FormatSpec<'a> { + fn from(old: generic_format_parser::FormatSpec<'a>) -> Self { + FormatSpec { + fill: old.fill, + fill_span: old.fill_span.map(Into::into), + align: old.align.into(), + sign: old.sign.map(Into::into), + alternate: old.alternate, + zero_pad: old.zero_pad, + debug_hex: old.debug_hex.map(Into::into), + precision: old.precision.into(), + precision_span: old.precision_span.map(Into::into), + width: old.width.into(), + width_span: old.width_span.map(Into::into), + ty: old.ty, + ty_span: old.ty_span.map(Into::into), + } + } + } + + impl From for DebugHex { + fn from(old: generic_format_parser::DebugHex) -> Self { + match old { + generic_format_parser::DebugHex::Lower => DebugHex::Lower, + generic_format_parser::DebugHex::Upper => DebugHex::Upper, + } + } + } + + impl<'a> From> for Count<'a> { + fn from(old: generic_format_parser::Count<'a>) -> Self { + match old { + generic_format_parser::Count::CountIs(x) => Count::CountIs(x), + generic_format_parser::Count::CountIsName(x, y) => Count::CountIsName(x, y.into()), + generic_format_parser::Count::CountIsParam(x) => Count::CountIsParam(x), + generic_format_parser::Count::CountIsStar(x) => Count::CountIsStar(x), + generic_format_parser::Count::CountImplied => Count::CountImplied, + } + } + } + + impl From for Sign { + fn from(old: generic_format_parser::Sign) -> Self { + match old { + generic_format_parser::Sign::Plus => Sign::Plus, + generic_format_parser::Sign::Minus => Sign::Minus, + } + } + } + + impl From for Alignment { + fn from(old: generic_format_parser::Alignment) -> Self { + match old { + generic_format_parser::Alignment::AlignLeft => Alignment::AlignLeft, + generic_format_parser::Alignment::AlignRight => Alignment::AlignRight, + generic_format_parser::Alignment::AlignCenter => Alignment::AlignCenter, + generic_format_parser::Alignment::AlignUnknown => Alignment::AlignUnknown, + } + } + } +} // FIXME: Rename? pub mod rust { @@ -22,7 +312,7 @@ pub mod rust { #[repr(C)] pub struct PieceSlice { - base_ptr: *const Piece<'static /* FIXME: That's wrong */>, + base_ptr: *const ffi::Piece<'static /* FIXME: That's wrong */>, len: usize, } @@ -32,7 +322,10 @@ pub extern "C" fn collect_pieces(input: *const libc::c_char) -> PieceSlice { let str = unsafe { CStr::from_ptr(input) }; // FIXME: No unwrap - let pieces = rust::collect_pieces(str.to_str().unwrap()); + let pieces: Vec> = rust::collect_pieces(str.to_str().unwrap()) + .into_iter() + .map(Into::into) + .collect(); PieceSlice { base_ptr: pieces.as_ptr(),