[Rust] ์ฐธ์กฐ: Cow

Cow๋Š” Clone on Write(Copy on Write)์— ๋Œ€ํ•œ ๋™์ž‘์„ ์ œ๊ณตํ•˜๋Š” enum ๊ธฐ๋ฐ˜ ๊ตฌํ˜„์ฒด๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ๋ถˆ๋ณ€ ์ฐธ์กฐ์— ๋Œ€ํ•œ ๊ฐ’์„ ๋“ค๊ณ  ์žˆ์œผ๋‚˜, write๋ฅผ ์‹œ๋„ํ•˜๋ฉด ๋ณต์ œ๋ฅผ ์‹œ๋„ํ•œ ํ›„์— ๋ณ€๊ฒฝ๋œ ๋ณต์ œ๋ณธ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ˜•ํƒœ์˜ ๋™์ž‘์„ ์ œ๊ณตํ•œ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ์ด๋Ÿฐ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง„ enum์ด๋‹ค.
ํ‰์ƒ์‹œ์—๋Š” Borrowed๋กœ ์ฐธ์กฐ๊ฐ’๋งŒ์„ ๋“ค๊ณ  ์žˆ๋‹ค๊ฐ€, ์ˆ˜์ •์ด ๋ฐœ์ƒํ•˜๋ฉด ๋ณต์ œ๋ณธ์„ ๋งŒ๋“ค์–ด์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ํฌ๊ธฐ๊ฐ€ ํด ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์— ๋Œ€ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์šฉ์ดํ•˜๋‹ค.
C++๋„ C++11 ์ด์ „์—๋Š” string์ด Cow ๊ธฐ๋ฐ˜ ๊ตฌํ˜„์ฒด์˜€๋˜ ์ ์ด ์žˆ๋‹ค.

ํ•œ๋ฒˆ ์ง์ ‘ Cow์˜ ์š”๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋™์ž‘ ๋ฐฉ์‹์„ ํ™•์ธํ•ด๋ณด์ž.
๋‚ด ๊ฒฝ์šฐ์—๋Š” ๊ฐ„๋‹จํ•œ ๋ฌธ์ž์—ด ๋ž˜ํผ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

์ถœ๋ ฅ๊ณผ ์žฌ์„ค์ • ๋ฉ”์„œ๋“œ ์ •๋„๋งŒ ์ฑ„์›Œ๋„ฃ๊ณ 


ToOwned ํŠธ๋ ˆ์ž‡์„ ๊ตฌํ˜„ํ•œ๋‹ค. Cow์— ๋„ฃ์œผ๋ ค๋ฉด ์ด๊ฒŒ ํ•„์ˆ˜์กฐ๊ฑด์ด๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋ณต์ œ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๋กœ๊ทธ๋„ ํ•œ์ค„ ์ฐ์—ˆ๋‹ค.


๊ทธ๋ฆฌ๊ณ  MyString->Cow๋กœ์˜ ๋ณ€ํ™˜ ๋™์ž‘์„ ๊ตฌํ˜„ํ•œ๋‹ค.
Borrowed๋กœ ์ฐธ์กฐ๋กœ ์ดˆ๊ธฐ ์ƒ์„ฑ์„ ํ•˜๋„๋ก ํ–ˆ๋‹ค. ๊ทธ๋Ÿฌ์ง€ ์•Š์œผ๋ฉด Cow๋ฅผ ์“ฐ๋Š” ์˜๋ฏธ๊ฐ€ ์—†๋‹ค.

๊ทธ๋Ÿฌ๊ณ  ๋‚˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Cow::from์œผ๋กœ ์ฐธ์กฐ ๊ธฐ๋ฐ˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ทธ๋ƒฅ ๋ถˆ๋ณ€ ๋™์ž‘์œผ๋กœ ์“ธ ๋•Œ๋Š” ๋Œ€์ถฉ ์“ฐ๋‹ค๊ฐ€, ์ˆ˜์ • ๋™์ž‘์ด ํ•„์š”ํ•˜๋ฉด to_mut๋กœ mutable ์ฐธ์กฐ๋ฅผ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
to_mut ์‹œ์ ์— ์ƒ์„ฑ๋˜๋Š” mutable ์ฐธ์กฐ๋Š” ์›๋ณธ ๊ฐ์ฒด์™€๋Š” ๋ฌด๊ด€ํ•˜๋ฉฐ, to_owned๋กœ ๋ณต์ œ๋œ ์ƒˆ ๊ฐ์ฒด์ผ ๋ฟ์ด๋‹ค.


์‹ค์ œ๋กœ ๋Œ๋ ค๋ด๋„ ์˜๋„ํ•œ๋Œ€๋กœ ์ฐํž ๊ฒƒ์ด๋‹ค.

์•„๋ž˜๋Š” ์ „์ฒด ์ฝ”๋“œ๋‹ค.

use std::borrow::Cow;

struct MyString(pub String);

impl MyString {
    fn show(&self) {
        println!("{}", self.0);
    }

    fn reset(&mut self, s: &str) {
        self.0.clear();
        self.0.push_str(s);
    }
}

impl ToOwned for MyString {
    type Owned = MyString;
    fn to_owned(&self) -> MyString {
        println!("๋ณต์ œ๋จ");
        MyString(self.0.clone())
    }
}

impl<'a> From<&'a MyString> for Cow<'a, MyString> {
    fn from(s: &'a MyString) -> Cow<'a, MyString> {
        Cow::Borrowed(s)
    }
}

fn main() {
    let big_str = MyString("very big string".to_string());

    let input = Cow::from(&big_str);

    input.show();
    println!("big_str: {:?}", big_str.0);

    let mut input = Cow::from(&big_str);

    {
        let big_str_2 = input.to_mut();
        big_str_2.reset("reset string");

        println!("big_str_2: {:?}", big_str_2.0);
    }

    input.show();
    println!("big_str: {:?}", big_str.0);
}

์ฐธ์กฐ
https://doc.rust-lang.org/std/borrow/enum.Cow.html
https://dhghomon.github.io/easy_rust/Chapter_42.html