Decode a UTF-8 string to character byte counts Given a UTF-8 string, give a string that represents byte counts of each characters.

Rules:


As long as the input string is encoded in UTF-8 (without BOM), its type doesn't matter. In C++, it can be char[] or std::string. In Haskell, it can be [Int8] or [CChar].
The output must be (in usual case) a string of ASCII digit characters. Its encoding doesn't matter.
When given an invalid UTF-8 sequence (including representation of surrogates), every bytes of the sequence are to be represented as the replacement character �.
Reserved characters and noncharacters are still considered as valid UTF-8 sequences, and thus must have corresponding output digit.
As this is a code-golf, the shortest code in bytes wins.


Example:

When given the following byte sequence:

00 80 C0 80 EB 80 80


The output must be:

1���3
Python 3, 135 bytes



def f(b):
&#9;B=b.decode(errors="ignore")[:1].encode();l=len(B)
&#9;if B and b[:l]!=B:return"�"+f(b[1:])
&#9;return str(l)+f(b[l:])if b else''


Try it online!

Explanation:

def f(b):
&#9;B=b.decode(errors="ignore")[:1].encode();l=len(B)
&#9; # B is the UTF-8-encoded version of the first Unicode character in the given bytes
&#9; # (Or the Nth, if the first N-1 bytes were invalid Unicode bytes)
&#9;if B and b[:l]!=B:return"�"+f(b[1:])
&#9; # If the two encoded byte-strings don't match,
&#9; # then the first byte in b is invalid,
&#9; # so append "�" to the returned string, and recurse
&#9;return str(l)+f(b[l:])if b else''
&#9; # If the byte-string is not empty,
&#9; #  append the length of the first character and recurse.
&#9; # Else (the input is empty) return the empty string (recursion base case)