mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Merge #417
417: Separate Writer::write_string and fmt::Write::write_str methods r=phil-opp a=phil-opp Avoids confusion by using different names for the two methods (and keeping them both) instead of naming both `write_str` as before.
This commit is contained in:
@@ -201,7 +201,7 @@ To print whole strings, we can convert them to bytes and print them one-by-one:
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
impl Writer {
|
impl Writer {
|
||||||
pub fn write_str(&mut self, s: &str) {
|
pub fn write_string(&mut self, s: &str) {
|
||||||
for byte in s.bytes() {
|
for byte in s.bytes() {
|
||||||
self.write_byte(byte)
|
self.write_byte(byte)
|
||||||
}
|
}
|
||||||
@@ -221,7 +221,7 @@ pub fn print_something() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
writer.write_byte(b'H');
|
writer.write_byte(b'H');
|
||||||
writer.write_str("ello");
|
writer.write_string("ello");
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
It first creates a new Writer that points to the VGA buffer at `0xb8000`. The syntax for this might seem a bit strange: First, we cast the integer `0xb8000` as an mutable [raw pointer]. Then we convert it to a mutable reference by dereferencing it (through `*`) and immediately borrowing it again (through `&mut`). This conversion requires an [`unsafe` block], since the compiler can't guarantee that the raw pointer is valid.
|
It first creates a new Writer that points to the VGA buffer at `0xb8000`. The syntax for this might seem a bit strange: First, we cast the integer `0xb8000` as an mutable [raw pointer]. Then we convert it to a mutable reference by dereferencing it (through `*`) and immediately borrowing it again (through `&mut`). This conversion requires an [`unsafe` block], since the compiler can't guarantee that the raw pointer is valid.
|
||||||
@@ -315,23 +315,21 @@ impl Writer {
|
|||||||
Instead of a normal assignment using `=`, we're now using the `write` method. This guarantees that the compiler will never optimize away this write.
|
Instead of a normal assignment using `=`, we're now using the `write` method. This guarantees that the compiler will never optimize away this write.
|
||||||
|
|
||||||
### Formatting Macros
|
### Formatting Macros
|
||||||
It would be nice to support Rust's formatting macros, too. That way, we can easily print different types like integers or floats. To support them, we need to implement the [core::fmt::Write] trait. The only required method of this trait is `write_str` that looks quite similar to our `write_str` method. To implement the trait, we just need to move it into an `impl fmt::Write for Writer` block and add a return type:
|
It would be nice to support Rust's formatting macros, too. That way, we can easily print different types like integers or floats. To support them, we need to implement the [`core::fmt::Write`] trait. The only required method of this trait is `write_str` that looks quite similar to our `write_string` method, just with a `fmt::Result` return type:
|
||||||
|
|
||||||
[core::fmt::Write]: https://doc.rust-lang.org/nightly/core/fmt/trait.Write.html
|
[`core::fmt::Write`]: https://doc.rust-lang.org/nightly/core/fmt/trait.Write.html
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
impl fmt::Write for Writer {
|
impl fmt::Write for Writer {
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
for byte in s.bytes() {
|
self.write_string(s);
|
||||||
self.write_byte(byte)
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
The `Ok(())` is just a `Ok` Result containing the `()` type. We can drop the `pub` because trait methods are always public.
|
The `Ok(())` is just a `Ok` Result containing the `()` type.
|
||||||
|
|
||||||
Now we can use Rust's built-in `write!`/`writeln!` formatting macros:
|
Now we can use Rust's built-in `write!`/`writeln!` formatting macros:
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,17 @@ impl Writer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Writes the given ASCII string to the buffer.
|
||||||
|
///
|
||||||
|
/// Wraps lines at `BUFFER_WIDTH`. Supports the `\n` newline character. Does **not**
|
||||||
|
/// support strings with non-ASCII characters, since they can't be printed in the VGA text
|
||||||
|
/// mode.
|
||||||
|
fn write_string(&mut self, s: &str) {
|
||||||
|
for byte in s.bytes() {
|
||||||
|
self.write_byte(byte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Shifts all lines one line up and clears the last row.
|
/// Shifts all lines one line up and clears the last row.
|
||||||
fn new_line(&mut self) {
|
fn new_line(&mut self) {
|
||||||
for row in 1..BUFFER_HEIGHT {
|
for row in 1..BUFFER_HEIGHT {
|
||||||
@@ -125,15 +136,8 @@ impl Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Write for Writer {
|
impl fmt::Write for Writer {
|
||||||
/// Writes the given ASCII string to the buffer.
|
|
||||||
///
|
|
||||||
/// Wraps lines at `BUFFER_WIDTH`. Supports the `\n` newline character. Does **not**
|
|
||||||
/// support strings with non-ASCII characters, since they can't be printed in the VGA text
|
|
||||||
/// mode.
|
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
for byte in s.bytes() {
|
self.write_string(s);
|
||||||
self.write_byte(byte)
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user