class TestCase::Unicode {
  use Unicode;

  static method ERROR_INVALID_UTF8 : int () {
    
    unless (Unicode->ERROR_INVALID_UTF8 == -2) {
      return 0;
    }
    
    return 1;
  }

  static method uchar : int () {
    
    {
      my $str = "あaい";
      
      my $pos = 0;
      
      # あ
      {
        my $uchar = Unicode->uchar($str, \$pos);

        unless ($uchar == 0x3042) {
          return 0;
        }
        
        unless ($pos == 3) {
          return 0;
        }
      }

      # a
      {
        my $uchar = Unicode->uchar($str, \$pos);

        unless ($uchar == 'a') {
          return 0;
        }
        
        unless ($pos == 4) {
          return 0;
        }
      }

      # い
      {
        my $uchar = Unicode->uchar($str, \$pos);

        unless ($uchar == 0x3044) {
          return 0;
        }
        
        unless ($pos == 7) {
          return 0;
        }
      }
      
      # End
      {
        my $uchar = Unicode->uchar($str, \$pos);
      
        unless ($uchar == -1) {
          return 0;
        }
      }
    }

    {
      my $str = "あaい";
      my $code_points = [0x3042, 'a', 0x3044];
      
      my $pos = 0;
      my $i = 0;
      while ((my $uchar = Unicode->uchar($str, \$pos)) >= 0) {
        
        unless ($uchar == $code_points->[$i]) {
          return 0;
        }
        
        $i++;
      }
    }
      
    return 1;
  }

  static method uchar_to_utf8 : int () {
    
    {
      my $pos = 0;
      
      # あ
      {
        my $uchar = 0x3042;
        my $utf8_bytes = Unicode->uchar_to_utf8($uchar);
        my $len = length $utf8_bytes;
        unless ($len == 3) {
          return 0;
        }
        unless ($utf8_bytes eq "あ") {
          return 0;
        }
      }

      # a
      {
        my $uchar = 'a';
        my $utf8_bytes = Unicode->uchar_to_utf8($uchar);
        my $len = length $utf8_bytes;
        unless ($len == 1) {
          return 0;
        }
        unless ($utf8_bytes eq "a") {
          return 0;
        }
      }

      # い
      {
        my $uchar = 0x3044;
        my $utf8_bytes = Unicode->uchar_to_utf8($uchar);
        my $len = length $utf8_bytes;
        unless ($len == 3) {
          return 0;
        }
        unless ($utf8_bytes eq "い") {
          return 0;
        }
      }
    }
    return 1;
  }

  static method utf32_to_utf16 : int () {
    # あaい
    {
      my $u32chars = [0x3042, 'a', 0x3044];
      
      my $u16chars = Unicode->utf32_to_utf16($u32chars);
      
      unless ($u16chars->[0] == $u32chars->[0]) {
        return 0;
      }
      unless ($u16chars->[1] == $u32chars->[1]) {
        return 0;
      }
      
      unless ($u16chars->[2] == $u32chars->[2]) {
        return 0;
      }
    }

    # あ𠮷a(サロゲートペア)
    {
      my $u32chars = [0x3042, 0x20bb7, 'a'];
      
      my $u16chars = Unicode->utf32_to_utf16($u32chars);
      
      unless (@$u16chars == 4) {
        return 0;
      }
      
      unless ($u16chars->[0] == 0x3042) {
        return 0;
      }
      unless ($u16chars->[1] == (short)0xd842) {
        return 0;
      }
      unless ($u16chars->[2] == (short)0xdfb7) {
        return 0;
      }
      
      unless ($u16chars->[3] == 'a') {
        return 0;
      }
    }
    
    return 1;
  }

  static method utf16_to_utf32 : int () {
    # あaい
    {
      my $u16chars = [(short)0x3042, 'a', 0x3044];
      
      my $u32chars = Unicode->utf16_to_utf32($u16chars);
      
      unless ($u32chars->[0] == $u16chars->[0]) {
        return 0;
      }
      unless ($u32chars->[1] == $u16chars->[1]) {
        return 0;
      }
      
      unless ($u32chars->[2] == $u16chars->[2]) {
        return 0;
      }
    }

    # あ𠮷a(サロゲートペア)
    {
      my $u16chars = [(short)0x3042, (short)0xd842, (short)0xdfb7, 'a'];
      
      my $u32chars = Unicode->utf16_to_utf32($u16chars);
      
      unless ($u32chars->[0] == 0x3042) {
        return 0;
      }
      
      unless ($u32chars->[1] == 0x20bb7) {
        return 0;
      }
      unless ($u32chars->[2] == 'a') {
        return 0;
      }
    }
    
    return 1;
  }

  static method utf8_to_utf16 : int () {
    # サロゲートペア含む
    my $str = "あ𠮷a";
    
    my $u16chars = Unicode->utf8_to_utf16($str);
    
    unless (@$u16chars == 4) {
      return 0;
    }
    unless ($u16chars->[0] == 0x3042) {
      return 0;
    }
    unless ($u16chars->[1] == (short)0xd842) {
      return 0;
    }
    unless ($u16chars->[2] == (short)0xdfb7) {
      return 0;
    }
    
    unless ($u16chars->[3] == 'a') {
      return 0;
    }
    
    return 1;
  }

  static method utf16_to_utf8 : int () {
    # サロゲートペア含む
    my $u16chars = [(short)0x3042, (short)0xd842, (short)0xdfb7, 'a'];
    
    my $str = Unicode->utf16_to_utf8($u16chars);
    
    unless ($str eq "あ𠮷a") {
      return 0;
    }
    
    return 1;
  }
  
  static method is_unicode_scalar_value : int () {
    
    if (Unicode->is_unicode_scalar_value(-1)) {
      return 0;
    }
    
    unless (Unicode->is_unicode_scalar_value(0)) {
      return 0;
    }

    unless (Unicode->is_unicode_scalar_value(0xD800 - 1)) {
      return 0;
    }

    if (Unicode->is_unicode_scalar_value(0xD800)) {
      return 0;
    }

    if (Unicode->is_unicode_scalar_value(0xD800 + 10)) {
      return 0;
    }

    if (Unicode->is_unicode_scalar_value(0xDFFF)) {
      return 0;
    }
    
    unless (Unicode->is_unicode_scalar_value(0xDFFF + 1)) {
      return 0;
    }

    unless (Unicode->is_unicode_scalar_value(0x10FFFF)) {
      return 0;
    }
    
    if (Unicode->is_unicode_scalar_value(0x10FFFF + 1)) {
      return 0;
    }
    
    return 1;
  }
}