Yeah, I love this low level stuff. Anyway, I came up with this:

```c
int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
{
	size_t p;
	int v;
	int shift[] = {4, 0};

	assert(out && str);

	if (!length)
		return oid_error_invalid("too short");

	if (length > GIT_OID_HEXSZ)
		return oid_error_invalid("too long");

	memset(out->id, 0, GIT_OID_RAWSZ);

	for (p = 0; p < length; p++) {
		v = git__fromhex(str[p]);
		if (v < 0)
			return oid_error_invalid("contains invalid characters");

		out->id[p / 2] |= (unsigned char)(v << shift[p % 2]);
	}

	return 0;
}
```

It suspiciously seems to work and passes the tests but I need to review it properly tomorrow. And now to get some sleep, it's 2:30 AM here :night_with_stars: