You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: template.rs
    path of file: ./repos/boa/core/parser/src/lexer
    
    the code of the file until where you have to start completion: //! Boa's lexing for ECMAScript template literals.

use crate::{
    lexer::{string::UTF16CodeUnitsBuffer, Cursor, Error, Token, TokenKind, Tokenizer},
    source::ReadChar,
};
use boa_ast::{Position, Span};
use boa_interner::{Interner, Sym};
use boa_profiler::Profiler;
use std::io::{self, ErrorKind};

#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TemplateString {
    /// The raw template string.
    raw: Sym,

    /// The cooked template string.
    cooked: Option<Sym>,
}

impl TemplateString {
    /// Creates a new `TemplateString` with the given raw template ans start position.
    pub fn new(raw: Sym, interner: &mut Interner) -> Self {
        Self {
            raw: Self::as_raw(raw, interner),
            cooked: Self::as_cooked(raw, interner),
        }
    }

    /// Returns the raw template string.
    pub fn raw(self) -> Sym {
        self.raw
    }

    /// Returns the cooked template string if it exists.
    pub fn cooked(self) -> Option<Sym> {
        self.cooked
    }

    /// Converts the raw template string into a mutable string slice.
    ///
    /// More information:
    ///  - [ECMAScript reference][spec]
    ///
    /// [spec]: https://tc39.es/ecma262/#sec-static-semantics-templatestrings
    fn as_raw(raw: Sym, interner: &mut Interner) -> Sym {
        let string = interner.resolve_expect(raw).utf16();
        let mut iter = string.iter().peekable();
        let mut buf: Vec<u16> = Vec::new();
        loop {
            match iter.next() {
                Some(0x5C /* \ */) => {
                    buf.push_code_point(0x5C);
                    match iter.next() {
                        Some(0x0D /* <CR> */) => {
                            buf.push_code_point(0x0A);
                        }
                        Some(ch) => {
                            buf.push_code_point(u32::from(*ch));
                        }
                        None => break,
                    }
                }
                Some(0x0D /* <CR> */) => {
                    buf.push_code_point(0x0A);
                }
                Some(ch) => {
                    buf.push_code_point(u32::from(*ch));
                }
                None => break,
            }
        }
        interner.get_or_intern(buf.as_slice())
    }

    /// Creates a new cooked template string. Returns a lexer error if it fails to cook the
    /// template string.
    ///
  
    
    fn as_cooked(raw: Sym, interner: &mut Interner) -> Option<Sym> {
        let string = interner.resolve_expect(raw).utf16();
        let mut iter = string.iter().peekable();
        let mut buf: Vec<u16> = Vec::new();

        loop {
            match iter.next() {
                Some(0x5C /* \ */) => {
                    let escape_value = match iter.next() {
                        Some(0x62 /* b */) => 0x08 /* <BS> */,
                        Some(0x74 /* t */) => 0x09 /* <HT> */,
                        Some(0x6E /* n */) => 0x0A /* <LF> */,
                        Some(0x76 /* v */) => 0x0B /* <VT> */,
                        Some(0x66 /* f */) => 0x0C /* <FF> */,
                        Some(0x72 /* r */) => 0x0D /* <CR> */,
                        Some(0x22 /* " */) => 0x22 /* " */,
                        Some(0x27 /* ' */) => 0x27 /* ' */,
                        Some(0x5C /* \ */) => 0x5C /* \ */,
                        Some(0x30 /* 0 */) if iter
                            .peek()
                            .filter(|ch| (0x30..=0x39 /* 0..=9 */).contains(**ch))
                            .is_none() => 0x00 /* NULL */,
                        // Hex Escape
                        Some(0x078 /* x */) => {
                            let mut s = String::with_capacity(2);
                            s.push(char::from_u32(u32::from(*iter.next()?))?);
                            s.push(char::from_u32(u32::from(*iter.next()?))?);
                            u16::from_str_radix(&s, 16).ok()?.into()
                        }
                        // Unicode Escape
                        Some(0x75 /* u */) => {
                            let next = *iter.next()?;
                            if next ==  0x7B /* { */ {
                                let mut buffer = String::with_capacity(6);
                                loop {
                                    let next = *iter.next()?;
                                    if next == 0x7D /* } */ {
                                        break;
                                    }
                                    buffer.push(char::from_u32(u32::from(next))?);
                                }
                                let cp = u32::from_str_radix(&buffer, 16).ok()?;
                                if cp > 0x10_FFFF {
                                    return None;
                                }
                                cp
                            } else {
                                let mut s = String::with_capacity(4);
                                s.push(char::from_u32(u32::from(next))?);
                                s.push(char::from_u32(u32::from(*iter.next()?))?);
                                s.push(char::from_u32(u32::from(*iter.next()?))?);
                                s.push(char::from_u32(u32::from(*iter.next()?))?);
                                u16::from_str_radix(&s, 16).ok()?.into()
                            }
                        }
                        // NonOctalDecimalEscapeSequence
                        Some(0x38 /* 8 */ | 0x39 /* 9 */) => {
                            return None;
                        }
                        // LegacyOctalEscapeSequence
                        Some(ch) if (0x30..=0x37 /* '0'..='7' */).contains(ch) => {
                            return None;
                        }
                        // Line Terminator
                        Some(0x0A /* <LF> */ | 0x0D /* <CR> */ | 0x2028 /* <LS> */ | 0x2029 /* <PS> */) => {
                            continue;
                        }
                        Some(ch) => {
                            u32::from(*ch)
                        }
                        None => return None,
                    };
                    buf.push_code_point(escape_value);
                }
                Some(0x0D /* <CR> */) => {
                    buf.push_code_point(0x0A);
                }
                Some(ch) => {
                    buf.push_code_point(u32::from(*ch));
                }
                None => break,
            }
        }

        Some(interner.get_or_intern(buf.as_slice()))
    }