make_idna_table.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. # Copyright 2013-2014 Valentin Gosu.
  2. #
  3. # Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  4. # http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  5. # <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  6. # option. This file may not be copied, modified, or distributed
  7. # except according to those terms.
  8. # Run as: python make_idna_table.py idna_table.txt > src/idna_table.rs
  9. # You can get the latest idna table from
  10. # http://www.unicode.org/Public/idna/latest/IdnaMappingTable.txt
  11. print('''\
  12. // Copyright 2013-2014 Valentin Gosu.
  13. //
  14. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  15. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  16. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  17. // option. This file may not be copied, modified, or distributed
  18. // except according to those terms.
  19. // Generated by make_idna_table.py
  20. ''')
  21. print('''\
  22. #[allow(non_camel_case_types)]
  23. pub enum MappingStatus {
  24. valid,
  25. ignored,
  26. mapped,
  27. deviation,
  28. disallowed,
  29. disallowed_STD3_valid,
  30. disallowed_STD3_mapped,
  31. }
  32. pub struct Mapping {
  33. pub from: char,
  34. pub to: char,
  35. pub status: MappingStatus,
  36. pub mapping: &'static [char],
  37. }
  38. ''')
  39. print("static NONE: [char;0] = [];")
  40. txt = open("IdnaMappingTable.txt")
  41. line_no = 0
  42. for line in txt:
  43. # remove comments
  44. head, sep, tail = line.partition('#')
  45. # skip empty lines
  46. if len(head.strip()) == 0:
  47. continue
  48. line_no = line_no + 1
  49. txt = open("IdnaMappingTable.txt")
  50. print("pub static TABLE: &'static [Mapping] = &[")
  51. def char(s):
  52. return "'%s'" % unichr(int(s, 16)).replace('\\', '\\\\').replace('\'', '\\\'').encode('utf8')
  53. mappings = []
  54. for line in txt:
  55. # remove comments
  56. head, sep, tail = line.partition('#')
  57. # skip empty lines
  58. if len(head.strip()) == 0:
  59. continue
  60. table_line = head.split(';')
  61. if table_line[0].strip() == 'D800..DFFF':
  62. continue # Surrogates don't occur in Rust strings.
  63. first, sep, last = table_line[0].strip().partition('..')
  64. if len(last)==0:
  65. last = first
  66. mapping = "NONE"
  67. if len(table_line)>2:
  68. if len(table_line[2].strip())>0:
  69. codes = table_line[2].strip().split(' ')
  70. newmap = ""
  71. for code in codes:
  72. newmap = newmap + char(code) + ", "
  73. newmap = "[" + newmap + "]"
  74. mapping = "MAPPING_%s_%s" % (first, last)
  75. static_array = "static %s : [char; %d] = %s;" % (mapping, len(codes), newmap)
  76. mappings.append(static_array)
  77. print " Mapping{ from: %s, to: %s, status: MappingStatus::%s, mapping: &%s }," % (char(first), char(last), table_line[1].strip(), mapping)
  78. print("];")
  79. for mapping in mappings:
  80. print mapping