docs: @SuppressWarnings("unchecked")
      public <T> T convert(Object source, String syntax, Class<T> toClass) {
          Object result = null;
  
          // What are we converting form
          Class<?> fromClass = source.getClass();
  
          // Deal with primitives
          Class<?> targetClass = toClass;
          if (toClass.isPrimitive()) {
              targetClass = primitiveTypeMap.get(toClass);
          }
  
          // Try to convert with any syntax we have been given
          Converter syntaxConverter = converters.get(makeConverterKey(fromClass, syntax, targetClass));
          if (syntaxConverter != null) {
              try {
                  result = syntaxConverter.convert(source, targetClass);
              } catch (Exception e) {
                  // Ignore as we may still be able to convert successfully
              }
          }
  
          // Do we actually need to do any conversion?
          if (result == null && targetClass.isAssignableFrom(fromClass)) {
              result = source;
          }
  
          // If we were given a syntax and we failed to convert drop back to any mapping
          // that will work from class -> to class
          if (result == null && syntax != null) {
              Converter nullSyntaxConverter = converters.get(makeConverterKey(fromClass, null, targetClass));
              if (nullSyntaxConverter != null) {
                  try {
                      result = nullSyntaxConverter.convert(source, targetClass);
                  } catch (Exception e) {
                      // Handled at the end of the method
                  }
              }
          }
  
          if (result == null) {
              throw new ConverterException(String.format(
                      "Cannot convert %1$s of class %2$s via syntax %3$s to class %4$s", source, source.getClass(),
                      syntax, toClass));
          }
  
          // We cannot do the safe thing of doing a .cast as we need to rely on auto-unboxing to deal with primitives!
          return (T)result;
      }