// These return the bool first so you can check in a conditional,
// rather than having to do '_, ok := ...'

check_type_tag :: ($$T: Type, tag: Type_Info_Tag) -> bool, *Type_Info {
   #if is_constant(T) {
      info :: type_info(T);
      if info.type == tag return true, info;
   }
   else {
      info := T.(*Type_Info);
      if info.type == tag return true, info;
   }

   return false, null;
}

type_is_integer :: ($$T: Type) -> bool, *Type_Info_Integer {
   ok, info := check_type_tag(T, .INTEGER);
   return ok, info.(*Type_Info_Integer);
}

type_is_float :: ($$T: Type) -> bool, *Type_Info_Float {
   ok, info := check_type_tag(T, .FLOAT);
   return ok, info.(*Type_Info_Float);
}

type_is_array :: ($$T: Type) -> bool, *Type_Info_Array {
   ok, info := check_type_tag(T, .ARRAY);
   return ok, info.(*Type_Info_Array);
}

type_is_struct :: ($$T: Type) -> bool, *Type_Info_Struct {
   ok, info := check_type_tag(T, .STRUCT);
   return ok, info.(*Type_Info_Struct);
}

// Can be passed directly to using,map
remap_snake_to_pascal :: (names: []string) {
   for names {
      names[it_index] = snake_to_pascal(it);
   }
}

snake_to_pascal :: (name: string) -> string {
   b: basic.String_Builder;

   upper := true;
   for i: 0..name.count - 1 {
      c := name[i];
      if c == #char "_" {
         upper = true;
         continue;
      }

      if upper {
         basic.append(*b, basic.to_upper(c));
         upper = false;
      } else {
         basic.append(*b, c);
      }
   }

   return basic.builder_to_string(*b);
}

rune_width :: (r: rune) -> int {
   if r < 0 return -1;

   if r <= 0x7F  return 1;
   if r <= 0x7FF return 2;

   if r >= 0xD800 &&
      r <= 0xDFFF return -1;

   if r <= 0xFFFF   return 3;
   if r <= 0x10FFFF return 4;

   return -1;
}


#scope_file;

#if RUN_TESTS #run {
   test.run("snake_to_pascal", t => {
      test.expect(t, snake_to_pascal("some_name")  == "SomeName");
      test.expect(t, snake_to_pascal("_some_name") == "SomeName");
      test.expect(t, snake_to_pascal("some__name") == "SomeName");
      test.expect(t, snake_to_pascal("some_name_") == "SomeName");
      test.expect(t, snake_to_pascal("X_Y_Z")      == "XYZ");
      test.expect(t, snake_to_pascal("XY_Z")       == "XYZ");
   });
}
