pub struct Size {
pub width: u16,
pub height: u16,
}Expand description
Terminal dimensions measured in character cells.
Fields§
§width: u16Number of columns.
height: u16Number of rows.
Implementations§
Source§impl Size
impl Size
Sourcepub const fn new(width: u16, height: u16) -> Self
pub const fn new(width: u16, height: u16) -> Self
Creates terminal dimensions from a column and row count.
Examples found in repository?
More examples
examples/chat/welcome.rs (line 170)
167 pub fn new(charset: Charset) -> Self {
168 Self {
169 charset,
170 frame: Frame::new(Size::new(0, 0)),
171 title: fmts!(" {} omp v{} ", charset.icon(Icon::Omp), env!("CARGO_PKG_VERSION")),
172 camera: (0.0, 0.0),
173 camera_target: (0.0, 0.0),
174 last_elapsed: 0.0,
175 logo_origin: (0, 0),
176 logo: [[None; LOGO_COLS]; LOGO_ROWS],
177 logo_at: None,
178 backdrop_frame: Frame::new(Size::new(0, 0)),
179 backdrop_at: None,
180 backdrop: Eclipse::default(),
181 surface: Surface::new(),
182 pointer: None,
183 hover: Tween::settled(0.0),
184 }
185 }examples/gallery/overlay.rs (line 54)
35pub(crate) fn show_picker(ui: &mut Ui) -> OverlayId {
36 ui.show_overlay(
37 dom! {
38 <box border=round title="Switch Model">
39 <col gap=1>
40 <text dim>{"Session-only switch — role models stay unchanged"}</text>
41 <select id=model>
42 for (value, label, stats) in MODELS {
43 <option value={value} desc={stats}>{label}</option>
44 }
45 </select>
46 </col>
47 </box>
48 },
49 OverlayOptions::default()
50 .anchor(OverlayAnchor::Center)
51 .width(Dim::Pct(70))
52 .min_width(48)
53 .max_height(Dim::Pct(60))
54 .min_viewport(Size::new(40, 8)),
55 )
56}examples/footers.rs (line 204)
199fn compose(scene: &Scene) -> Frame {
200 let height = STUDIES
201 .iter()
202 .map(|study| study.rows + 3)
203 .fold(3_u16, u16::saturating_add);
204 let mut frame = Frame::new(Size::new(scene.width, height));
205 frame.fill(Rect::new(0, 0, scene.width, height), ink(TEXT));
206
207 let column = frame.put(1, 0, "composer footer studies", ink(TEXT).bold());
208 frame.put(
209 column.saturating_add(2),
210 0,
211 "split + air gap, six session-title placements",
212 ink(MUTED),
213 );
214 frame.put(1, 1, "↑/↓ scroll · PgUp/PgDn page · Home/End jump · q quits", ink(FAINT));
215
216 let mut y = 3_u16;
217 for (index, study) in STUDIES.iter().enumerate() {
218 let number = fmts!("{:>2} ", index + 1);
219 let mut column = frame.put(1, y, &number, ink(GOLD).bold());
220 column = frame.put(column, y, study.title, ink(TEXT).bold());
221 column = frame.put(column, y, " ", ink(FAINT));
222 frame.put(column, y, study.note, ink(MUTED));
223 (study.draw)(&mut frame, y + 1, scene);
224 y = y.saturating_add(study.rows + 3);
225 }
226 frame
227}examples/chat/demo.rs (line 786)
752 pub fn new(ctx: &UiContext) -> Self {
753 let editor = Rc::new(RefCell::new({
754 let mut editor = Editor::new(EditorOptions::default());
755 editor.set_completion(Box::new(SlashCommands::new(demo_commands())));
756 editor
757 }));
758 let edit_outcome = Rc::new(RefCell::new(None));
759 let work = Rc::new(RefCell::new(WorkState {
760 working: true,
761 since: Duration::ZERO,
762 fade: Tween::settled(GREEN),
763 }));
764 let model = Rc::new(RefCell::new(Str::new_static("Fable 5++")));
765 let pane = EditorPane::new()
766 .input(DemoInput::new(Rc::clone(&editor), Rc::clone(&edit_outcome)))
767 .status(DemoStatus::new(Rc::clone(&work), Rc::clone(&model), ctx.charset));
768 let attachments = pane.attachments();
769 let editor_ui = Ui::from_root(pane, 0, ctx.clone());
770 Self {
771 started_at: Instant::now(),
772 ctx: ctx.clone(),
773 cancel_hint: ctx.charset.icon(Icon::Cancellable),
774 editor_ui,
775 editor,
776 edit_outcome,
777 work,
778 last_working: true,
779 model,
780 attachments,
781 transcript: vec![Entry::Command],
782 drawn_entries: 0,
783 transcript_rows: 0,
784 appended_messages: 0,
785 emitted_shards: 0,
786 last_viewport: Size::new(0, 0),
787 height_floor: 0,
788 frame: Frame::new(Size::new(0, 0)),
789 live_panel: None,
790 live_rows: std::array::from_fn(|_| LiveRowCache::new()),
791 live_label_scratch: StrMut::with_capacity(40),
792 right_inset: 0,
793 switch_requested: false,
794 }
795 }
796
797 /// Routes a key through the editor and reports whether the demo should
798 /// exit. Quit policy lives here, not in the editor: once the editor
799 /// reports a key unused, `esc` first cancels running work and only quits
800 /// at rest; `ctrl-c` always quits.
801 pub fn handle_key(&mut self, key: Key) -> bool {
802 *self.edit_outcome.borrow_mut() = None;
803 let _ = self.editor_ui.handle_key(key);
804 let outcome = self
805 .edit_outcome
806 .borrow_mut()
807 .take()
808 .unwrap_or(EditOutcome::Ignored);
809 match outcome {
810 EditOutcome::Submitted(text) => {
811 let trimmed = text.trim();
812 if trimmed == "/switch" {
813 self.switch_requested = true;
814 return false;
815 }
816 if let Some(path) = trimmed
817 .strip_prefix("/attach")
818 .filter(|rest| rest.is_empty() || rest.starts_with(' '))
819 {
820 let path = path.trim().to_string();
821 if !path.is_empty() {
822 self.attach_image(&path);
823 }
824 return false;
825 }
826 let _ = self.attachments.take();
827 self.refresh_composer();
828 self
829 .transcript
830 .push(Entry::Submitted(Box::new(Submission::new(
831 text,
832 Self::message_width(self.last_viewport.width),
833 &self.ctx,
834 ))));
835 self.set_working(true, self.started_at.elapsed());
836 false
837 },
838 EditOutcome::Changed => {
839 self.reconcile_attachments();
840 false
841 },
842 EditOutcome::Ignored => {
843 if key == Key::Ctrl('c') {
844 return true;
845 }
846 if key != Key::Esc {
847 return false;
848 }
849 if self.work.borrow().working {
850 self.set_working(false, self.started_at.elapsed());
851 return false;
852 }
853 true
854 },
855 }
856 }
857
858 /// Consumes a pending `/switch` request submitted through the composer.
859 pub fn take_switch_request(&mut self) -> bool {
860 std::mem::take(&mut self.switch_requested)
861 }
862
863 /// Routes a document-space mouse report into the editor UI.
864 pub fn handle_mouse(&mut self, report: &MouseReport) {
865 let editor_height = self.editor_ui.height();
866 let editor_y = self.frame.size().height.saturating_sub(editor_height);
867 let editor_bottom = editor_y.saturating_add(editor_height);
868 if report.row < editor_y || report.row >= editor_bottom {
869 return;
870 }
871 let _ = self
872 .editor_ui
873 .handle_mouse(report.col, report.row - editor_y, report.kind);
874 }
875
876 /// Switches the work state and retargets the brand fade. The status bar
877 /// repaints immediately and the fade departs from whatever color is on
878 /// screen, so rapid cancel/resume never snaps.
879 fn set_working(&mut self, working: bool, now: Duration) {
880 {
881 let mut work = self.work.borrow_mut();
882 if work.working == working {
883 return;
884 }
885 work.working = working;
886 work.since = now;
887 let target = if working { GREEN } else { MUTED };
888 work
889 .fade
890 .retarget(now, target, BRAND_FADE, Easing::EaseInOut);
891 }
892 self.editor_ui.invalidate(STATUS_ID);
893 }
894
895 /// Reflects a session model switch in the status bar's model segment.
896 pub fn set_model(&mut self, name: &str) {
897 *self.model.borrow_mut() = Str::from(name);
898 self.editor_ui.invalidate(STATUS_ID);
899 }
900
901 /// Routes sanitized bracketed paste text through the editor. Dropped
902 /// paths to existing image files (quoted, escaped, `file://`, or
903 /// multi-file) and any large paste collapse into composer attachment
904 /// chips instead of raw text.
905 pub fn handle_paste(&mut self, text: &str) {
906 let paths = omp_tui::paste::dropped_paths(text);
907 if !paths.is_empty()
908 && paths.iter().all(|path| {
909 omp_tui::paste::is_image_path(path) && std::path::Path::new(path.as_str()).is_file()
910 }) {
911 for path in &paths {
912 self.attach_image(path);
913 }
914 return;
915 }
916 if text.lines().count() > 10 || text.len() > 1000 {
917 self.attach_paste(text);
918 return;
919 }
920 let _ = self.editor_ui.handle_paste(text);
921 }
922
923 /// Routes Ctrl+Shift+V clipboard text into the composer verbatim: no
924 /// attachment staging, no large-paste collapse — the text stays inline
925 /// and editable.
926 pub fn handle_paste_raw(&mut self, text: &str) {
927 let _ = self.editor_ui.handle_paste_raw(text);
928 }
929
930 /// Stages `path` on the composer and mentions it in the prompt as an
931 /// atomic `<icon> #N` chip expanding to `<ref image=N/>` on submit.
932 fn attach_image(&mut self, path: &str) {
933 let attachment = self.attachments.push_image(path);
934 let payload = format!("<ref image={}/>", attachment.marker);
935 self.insert_chip(&attachment, &payload);
936 }
937
938 /// Collapses a large paste into a staged attachment card and an atomic
939 /// composer chip expanding back to the pasted text on submit.
940 fn attach_paste(&mut self, text: &str) {
941 let attachment = self.attachments.push_text(text);
942 self.insert_chip(&attachment, text);
943 }
944
945 /// Inserts one attachment chip as an atomic editor reference.
946 fn insert_chip(&mut self, attachment: &Attachment, payload: &str) {
947 let chip = chip_label(attachment, self.ctx.charset);
948 {
949 let mut editor = self.editor.borrow_mut();
950 let _ = editor.insert_reference(&chip, payload);
951 let _ = editor.insert_text(" ");
952 }
953 self.refresh_composer();
954 }
955
956 /// Hides staged attachments whose chip the user deleted from the
957 /// composer (and re-shows them after an undo). Presence is derived
958 /// from the buffer's atomic ranges, never from text matching.
959 fn reconcile_attachments(&mut self) {
960 let charset = self.ctx.charset;
961 let changed = {
962 let editor = self.editor.borrow();
963 let text = editor.text();
964 let ranges = editor.atom_ranges();
965 self.attachments.set_visible(|attachment| {
966 let chip = chip_label(attachment, charset);
967 ranges
968 .iter()
969 .any(|&(start, end)| text.get(start..end) == Some(chip.as_str()))
970 })
971 };
972 if changed {
973 self.refresh_composer();
974 }
975 }
976
977 /// Relayouts the composer after out-of-band state changed its height.
978 fn refresh_composer(&mut self) {
979 let width = self.editor_ui.frame().size().width;
980 if width > 0 {
981 self.editor_ui.resize(width);
982 }
983 }
984
985 /// Reserves `cols` at the right edge for a composited rail, so the
986 /// composer's right-docked chrome stays visible beside it. The next
987 /// render relayouts the editor at the narrowed width.
988 pub const fn set_right_inset(&mut self, cols: u16) {
989 self.right_inset = cols;
990 }
991
992 /// The width the composer may actually occupy at `viewport`.
993 fn composer_width(&self, viewport: Size) -> u16 {
994 viewport.width.saturating_sub(self.right_inset).max(1)
995 }
996
997 /// Updates the retained logical document and reports its repainted rows.
998 pub fn render(&mut self, viewport: Size) -> RenderedFrame<'_> {
999 self.render_at(viewport, self.started_at.elapsed())
1000 }
1001
1002 fn render_at(&mut self, viewport: Size, elapsed: Duration) -> RenderedFrame<'_> {
1003 if viewport.width == 0 || viewport.height == 0 {
1004 self.last_viewport = viewport;
1005 self.height_floor = 0;
1006 self.drawn_entries = 0;
1007 self.transcript_rows = 0;
1008 self.live_panel = None;
1009 self.frame = Frame::new(viewport);
1010 return RenderedFrame {
1011 frame: &self.frame,
1012 stable_rows: 0,
1013 damage: SmallVec::new(),
1014 };
1015 }
1016 let composer_width = self.composer_width(viewport);
1017 if self.editor_ui.frame().size().width != composer_width {
1018 self.editor_ui.resize(composer_width);
1019 }
1020 // Fires due animation wakes (the status bar's spinner and brand
1021 // fade) so the blit below picks up fresh retained pixels.
1022 self.editor_ui.tick(elapsed);
1023 let editor_changed = self.editor_ui.take_frame_damage();
1024
1025 // A viewport change starts a fresh renderer session: replay the
1026 // whole transcript log at the new width. Between rebuilds the log
1027 // is append-only and every drawn row is final, so selections over
1028 // transcript text stay anchored to it in every terminal.
1029 let rebuild = self.last_viewport != viewport;
1030 if rebuild {
1031 self.last_viewport = viewport;
1032 self.height_floor = 0;
1033 self.drawn_entries = 0;
1034 self.transcript_rows = 0;
1035 let message_width = Self::message_width(viewport.width);
1036 for entry in &mut self.transcript {
1037 if let Entry::Submitted(submission) = entry {
1038 submission.resize(message_width, &self.ctx);
1039 }
1040 }
1041 }
1042 while self.appended_messages < Self::visible_messages(elapsed) {
1043 self.transcript.push(Entry::Message(self.appended_messages));
1044 self.appended_messages += 1;
1045 }
1046 while self.emitted_shards < Self::finished_shards(elapsed) {
1047 self.emitted_shards += 1;
1048 self.transcript.push(Entry::ShardDone(self.emitted_shards));
1049 }
1050
1051 let mut new_rows = 0_u16;
1052 for entry in &self.transcript[self.drawn_entries..] {
1053 new_rows = new_rows.saturating_add(Self::entry_height(entry, viewport.width, &self.ctx));
1054 }
1055 let transcript_rows = self.transcript_rows.saturating_add(new_rows);
1056 let editor_height = self.editor_ui.height();
1057 // Native scrollback is append-only, so the logical document may
1058 // never shrink while the seam is live: band rows that close again
1059 // (extra input lines) become blank padding that heals as the
1060 // transcript grows.
1061 let natural_height = transcript_rows.saturating_add(Self::band_height(editor_height));
1062 self.height_floor = self.height_floor.max(natural_height);
1063 let document_height = self.height_floor.max(viewport.height);
1064 let transcript_damage_start = if rebuild { 0 } else { self.transcript_rows };
1065 let margin = u16::from(viewport.width >= 50);
1066 let content_width = viewport.width.saturating_sub(margin * 2);
1067 let editor_y = document_height.saturating_sub(editor_height);
1068 let title_y = editor_y.saturating_sub(1);
1069 let working_y = title_y.saturating_sub(1);
1070 let panel_height = LIVE_SHARD_ROWS + 2;
1071 let panel_y = working_y.saturating_sub(1).saturating_sub(panel_height);
1072 let panel = Rect::new(margin, panel_y, content_width, panel_height);
1073 let repaint_suffix = rebuild || new_rows > 0 || self.live_panel != Some(panel);
1074 if rebuild {
1075 self.frame = Frame::new(Size::new(viewport.width, document_height));
1076 } else {
1077 self.frame.resize_height(document_height, base_style());
1078 }
1079 if repaint_suffix {
1080 self.frame.fill(
1081 Rect::new(
1082 0,
1083 transcript_damage_start,
1084 viewport.width,
1085 document_height.saturating_sub(transcript_damage_start),
1086 ),
1087 base_style(),
1088 );
1089 }
1090
1091 // Paint the new transcript entries; rows above `transcript_rows`
1092 // are final and never repainted.
1093 let mut y = self.transcript_rows;
1094 for index in self.drawn_entries..self.transcript.len() {
1095 let used = self.draw_entry_at(index, y, viewport.width);
1096 y = y.saturating_add(used);
1097 }
1098 self.drawn_entries = self.transcript.len();
1099 self.transcript_rows = y;
1100
1101 // The live band repaints in place at the bottom of the document.
1102 let animation_frame = Self::animation_frame(elapsed);
1103 let panel_changed = draw_live_panel(
1104 &mut self.frame,
1105 &mut self.live_rows,
1106 &mut self.live_label_scratch,
1107 panel,
1108 repaint_suffix,
1109 self.emitted_shards,
1110 animation_frame,
1111 self.ctx.charset,
1112 );
1113 let working = self.work.borrow().working;
1114 let working_changed = self.last_working != working;
1115 if !repaint_suffix && self.last_working && !working {
1116 self
1117 .frame
1118 .fill(Rect::new(0, working_y, viewport.width, 1), base_style());
1119 }
1120 if working {
1121 Self::draw_working(&mut self.frame, working_y, elapsed, self.cancel_hint);
1122 }
1123 Self::draw_session_title(&mut self.frame, title_y, self.right_inset);
1124 if repaint_suffix || editor_changed {
1125 self
1126 .frame
1127 .blit(self.editor_ui.frame(), 0, editor_height, 0, editor_y);
1128 }
1129 let mut damage = SmallVec::new();
1130 if repaint_suffix {
1131 damage.push((transcript_damage_start, document_height));
1132 } else {
1133 if panel_changed {
1134 damage.push((panel_y, panel_y.saturating_add(panel_height)));
1135 }
1136 if working || working_changed {
1137 damage.push((working_y, working_y.saturating_add(1)));
1138 }
1139 if editor_changed {
1140 damage.push((editor_y, document_height));
1141 }
1142 }
1143 self.last_working = working;
1144 self.live_panel = Some(panel);
1145
1146 RenderedFrame { frame: &self.frame, stable_rows: self.transcript_rows, damage }
1147 }
1148
1149 fn generation(elapsed: Duration) -> u64 {
1150 u64::try_from(elapsed.as_millis() / EMIT_INTERVAL.as_millis()).unwrap_or(u64::MAX)
1151 }
1152
1153 fn animation_frame(elapsed: Duration) -> u64 {
1154 u64::try_from(elapsed.as_millis() / 80).unwrap_or(u64::MAX)
1155 }
1156
1157 fn visible_messages(elapsed: Duration) -> usize {
1158 let interval = MESSAGE_INTERVAL.as_millis();
1159 usize::try_from(elapsed.as_millis() / interval + 1)
1160 .unwrap_or(usize::MAX)
1161 .min(4)
1162 }
1163
1164 /// Shards whose permanent result line has been appended by `elapsed`:
1165 /// two per emit tick, capped well inside `u16` document heights.
1166 fn finished_shards(elapsed: Duration) -> u16 {
1167 u16::try_from(Self::generation(elapsed).saturating_mul(2).min(60_000))
1168 .expect("finished shard count is clamped")
1169 }
1170
1171 /// Rows the bottom live band occupies: the shard panel, a blank
1172 /// separator, the activity row, the title air row, and the editor
1173 /// block.
1174 const fn band_height(editor_height: u16) -> u16 {
1175 LIVE_SHARD_ROWS + 2 + 3 + editor_height
1176 }
1177
1178 /// Rows `entry` will occupy at `width`, including its trailing blank.
1179 fn entry_height(entry: &Entry, width: u16, ctx: &UiContext) -> u16 {
1180 match entry {
1181 Entry::Command => 5,
1182 Entry::Message(message) => {
1183 let mut scratch = Frame::new(Size::new(width, 48));
1184 Self::draw_message(&mut scratch, 0, *message, width, ctx.charset)
1185 },
1186 Entry::ShardDone(_) => 1,
1187 Entry::Submitted(submission) => submission.height().saturating_add(1),
1188 }
1189 }
1190
1191 const fn message_width(width: u16) -> u16 {
1192 let narrowed = width.saturating_sub(3);
1193 if narrowed == 0 { 1 } else { narrowed }
1194 }
1195
1196 /// Paints one transcript entry at `y` and returns the rows it used.
1197 fn draw_entry_at(&mut self, index: usize, y: u16, width: u16) -> u16 {
1198 Self::draw_entry(&mut self.frame, &self.transcript[index], y, width, &self.ctx)
1199 }
1200
1201 /// Paints `entry` into any frame at `y` and returns the rows it used,
1202 /// including the trailing blank.
1203 fn draw_entry(frame: &mut Frame, entry: &Entry, y: u16, width: u16, ctx: &UiContext) -> u16 {
1204 let margin = u16::from(width >= 50);
1205 let content_width = width.saturating_sub(margin * 2);
1206 match entry {
1207 Entry::Command => {
1208 draw_command_box(frame, Rect::new(margin, y, content_width, 4), ctx.charset);
1209 5
1210 },
1211 Entry::Message(message) => Self::draw_message(frame, y, *message, width, ctx.charset),
1212 Entry::ShardDone(shard) => {
1213 Self::draw_shard_done(frame, y, *shard, width, ctx.charset);
1214 1
1215 },
1216 Entry::Submitted(submission) => {
1217 draw_submission(frame, y, submission, ctx.charset);
1218 submission.height().saturating_add(1)
1219 },
1220 }
1221 }
1222
1223 /// Composes exactly one viewport of throwaway resize-drag content at the
1224 /// new geometry: the live band anchors to the bottom, then transcript
1225 /// entries are walked backward and rewrapped at `viewport.width` until
1226 /// the screen is full — O(viewport) work per drag frame, with the
1227 /// topmost entry sliced when it only partially fits. Retained transcript
1228 /// state is untouched, so the settle rebuild replays full history
1229 /// exactly once.
1230 pub fn render_resize_preview(&mut self, viewport: Size) -> Frame {
1231 let elapsed = self.started_at.elapsed();
1232 let mut frame = Frame::new(viewport);
1233 if viewport.width == 0 || viewport.height == 0 {
1234 return frame;
1235 }
1236 frame.fill(Rect::new(0, 0, viewport.width, viewport.height), base_style());
1237 let composer_width = self.composer_width(viewport);
1238 if self.editor_ui.frame().size().width != composer_width {
1239 self.editor_ui.resize(composer_width);
1240 }
1241 self.editor_ui.tick(elapsed);
1242
1243 // The live band, laid out exactly like the retained document's.
1244 let margin = u16::from(viewport.width >= 50);
1245 let content_width = viewport.width.saturating_sub(margin * 2);
1246 let editor_height = self.editor_ui.height();
1247 let editor_y = viewport.height.saturating_sub(editor_height);
1248 let title_y = editor_y.saturating_sub(1);
1249 let working_y = title_y.saturating_sub(1);
1250 let panel_height = LIVE_SHARD_ROWS + 2;
1251 let panel_y = working_y.saturating_sub(1).saturating_sub(panel_height);
1252 draw_live_panel(
1253 &mut frame,
1254 &mut self.live_rows,
1255 &mut self.live_label_scratch,
1256 Rect::new(margin, panel_y, content_width, panel_height),
1257 true,
1258 self.emitted_shards,
1259 Self::animation_frame(elapsed),
1260 self.ctx.charset,
1261 );
1262 if self.work.borrow().working {
1263 Self::draw_working(&mut frame, working_y, elapsed, self.cancel_hint);
1264 }
1265 Self::draw_session_title(&mut frame, title_y, self.right_inset);
1266 frame.blit(self.editor_ui.frame(), 0, editor_height, 0, editor_y);
1267
1268 // Transcript tail, bottom-up above the band.
1269 let mut remaining = panel_y;
1270 for entry in self.transcript.iter().rev() {
1271 if remaining == 0 {
1272 break;
1273 }
1274 let height = Self::entry_height(entry, viewport.width, &self.ctx);
1275 if height == 0 {
1276 continue;
1277 }
1278 if height <= remaining {
1279 remaining -= height;
1280 Self::draw_entry(&mut frame, entry, remaining, viewport.width, &self.ctx);
1281 } else {
1282 // Slice the bottom rows of the partially visible entry.
1283 let mut scratch = Frame::new(Size::new(viewport.width, height));
1284 scratch.fill(Rect::new(0, 0, viewport.width, height), base_style());
1285 Self::draw_entry(&mut scratch, entry, 0, viewport.width, &self.ctx);
1286 frame.blit(&scratch, height - remaining, remaining, 0, 0);
1287 remaining = 0;
1288 }
1289 }
1290 frame
1291 }Trait Implementations§
impl Copy for Size
impl Eq for Size
impl StructuralPartialEq for Size
Auto Trait Implementations§
impl Freeze for Size
impl RefUnwindSafe for Size
impl Send for Size
impl Sync for Size
impl Unpin for Size
impl UnsafeUnpin for Size
impl UnwindSafe for Size
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Convert
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Convert
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Convert
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Convert
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Compare self to
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more