wgpu_types/
compilation_info.rs1use alloc::string::String;
2use alloc::vec::Vec;
3
4#[cfg(any(feature = "serde", test))]
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone)]
12#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
13pub struct CompilationInfo<SL = SourceLocation> {
14 pub messages: Vec<CompilationMessage<SL>>,
16}
17
18impl<SL> Default for CompilationInfo<SL> {
19 fn default() -> Self {
20 Self {
21 messages: Default::default(),
22 }
23 }
24}
25
26#[derive(Debug, Clone)]
31#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32pub struct CompilationMessage<SL = SourceLocation> {
33 pub message: String,
35 pub message_type: CompilationMessageType,
37 pub location: Option<SL>,
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44#[repr(u8)]
45pub enum CompilationMessageType {
46 Error,
48 Warning,
50 Info,
52}
53
54#[derive(Copy, Clone, Debug, PartialEq, Eq)]
65#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
66pub struct SourceLocation {
67 pub line_number: u32,
69 pub line_position: u32,
72 pub offset: u32,
74 pub length: u32,
76}
77
78#[derive(Copy, Clone, Debug, PartialEq, Eq)]
89#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
90pub struct Utf16SourceLocation {
91 pub line_number: u32,
93 pub line_position: u32,
96 pub offset: u32,
98 pub length: u32,
100}
101
102impl SourceLocation {
103 pub fn to_utf16(&self, source: &str) -> Utf16SourceLocation {
105 let len_utf16 = |s: &str| s.chars().map(|c| c.len_utf16() as u32).sum::<u32>();
106 let start = self.offset as usize;
107 let end = start + self.length as usize;
108 let utf16_offset = len_utf16(&source[..start]);
109 let utf16_length = len_utf16(&source[start..end]);
110
111 let line_start = source[..start].rfind('\n').map_or(0, |pos| pos + 1);
112 let utf16_line_position = len_utf16(&source[line_start..start]) + 1;
113
114 Utf16SourceLocation {
115 line_number: self.line_number,
116 line_position: utf16_line_position,
117 offset: utf16_offset,
118 length: utf16_length,
119 }
120 }
121}
122
123impl Utf16SourceLocation {
124 pub fn to_utf8(&self, source: &str) -> SourceLocation {
126 fn map_utf16_to_utf8_offset(utf16_offset: u32, text: &str) -> u32 {
127 let mut utf16_i = 0;
128 for (utf8_index, c) in text.char_indices() {
129 if utf16_i >= utf16_offset {
130 return utf8_index as u32;
131 }
132 utf16_i += c.len_utf16() as u32;
133 }
134 if utf16_i >= utf16_offset {
135 text.len() as u32
136 } else {
137 log::error!("UTF16 offset {utf16_offset} is out of bounds for string {text}");
138 u32::MAX
139 }
140 }
141 let utf8_offset = map_utf16_to_utf8_offset(self.offset, source);
142 let utf8_length = map_utf16_to_utf8_offset(self.length, &source[utf8_offset as usize..]);
143
144 let prefix = &source[..utf8_offset as usize];
145 let line_start = prefix.rfind('\n').map(|pos| pos + 1).unwrap_or(0) as u32;
146 let utf8_line_position = utf8_offset - line_start + 1; SourceLocation {
149 line_number: self.line_number,
150 line_position: utf8_line_position,
151 offset: utf8_offset,
152 length: utf8_length,
153 }
154 }
155}